目录:

一、Adapter

1. 什么是Adapter?

2. Android中的常用Adapter(BaseAdapter、ArrayAdapter、SimpleAdapter、SimpleCursorAdapter)

二、AdapterView

1. AdapterView简介

2. AdapterView的子视图对象(ListView、GridView、Spinner)

三、ListView滑动列表形式

1. ListView介绍及使用基本流程(实现简单的微信界面)

请根据以下内容完成重构,并保持段落结构:

android:layout_width="match_parent"

android:layout_height="match_parent">

android:id="@+id/lv_wechat"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:visibility="invisible">

子元素布局(头像+昵称+聊天信息):

以下是重构后的代码:

```xml

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="horizontal">

android:id="@+id/iv_avatar1"

android:layout_width="0dp"

android:layout_weight="1"

android:layout_height="wrap_content"

android:src="@mipmap/liyue" />

android:layout_width="0dp"

android:layout_weight="5"

android:layout_height="wrap_content"

android:orientation="vertical">

android:id="@+id/tv_nickname1"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:textSize="20sp"

android:text="璃月" />

android:id="@+id/tv_endmessage1"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:textSize="10sp"

android:text="114514" />

```

以下是根据您提供的内容重构后的代码:

```java

// 创建一个名为BaseAdapter的抽象类,继承自BaseAdapter

public abstract class BaseAdapter extends BaseQuickAdapter {

public BaseAdapter(@Nullable List data) {

super(R.layout.item_news, data);

}

@Override

protected void convert(BaseViewHolder helper, Item item) {

// 将数据项绑定到视图上,具体实现根据需求自定义

}

}

```

效果预览:在布局文件中添加一个RecyclerView和相应的适配器,然后运行程序即可看到效果预览。

public class PracticeAdapter extends BaseAdapter {

private Context context; //上下文

private Integer layoutId; //布局子控件id

private List list; //数据源

public PracticeAdapter() {}

//构造器

public PracticeAdapter(Context context, Integer layoutId, List list){

this.context = context;

this.layoutId = layoutId;

this.list = list;

}

//继承BaseAdapter需重写的四个方法

public int getCount() {

return list.size();

}//数据个数

public Object getItem(int position) {

return list.get(position);

}//对应位置的item

public long getItemId(int position) {

return position;

}//返回item下标位置

//getView最重要的一个函数,position当前item的下标,convertView当前的视图,parent当前视图的父视图

public View getView(int position, View convertView, ViewGroup parent) {

if(convertView == null){

convertView = LayoutInflater.from(context).inflate(layoutId, null);

}

//获取列表项中的控件

ImageView iv_avatar1 = convertView.findViewById(R.id.iv_avatar1);

TextView tv_nickname1 = convertView.findViewById(R.id.tv_nickname1);

TextView tv_endmessage1 = convertView.findViewById(R.id.tv_endmessage1);

//给数据项填充数据

Practice practice = list.get(position);

iv_avatar1.setImageResource(practice.getAvatar());

tv_nickname1.setText(practice.getNickName());

tv_endmessage1.setText(practice.getEndMessage());

//返回列表项

return convertView;

}

}

首先,我们需要在`onCreate`方法中创建一个`ListView`实例,并设置其布局文件。然后,我们需要创建一个自定义的`ArrayAdapter`类,继承自`BaseAdapter`,用于处理数据和视图之间的绑定。最后,我们需要在`onCreate`方法中初始化`ListView`,并为其设置适配器。

以下是重构后的代码:

```java

public class MainActivity extends AppCompatActivity {

private ListView listView;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

listView = findViewById(R.id.listView);

List practiceList = Practice.getPractice();

ArrayAdapter adapter = new PracticeArrayAdapter(this, practiceList);

listView.setAdapter(adapter);

}

public static class Practice {

private Integer avatar; //头像

private String nickName; //昵称

private String endMessage; //聊天信息

public Practice() {}

public Practice(Integer avatar, String nickName, String endMessage) {

this.avatar = avatar;

this.nickName = nickName;

this.endMessage = endMessage;

}

//数据源 包括头像,昵称,聊天信息

public static List getPractice() {

List list = new ArrayList<>();

list.add(new Practice(R.mipmap.liyue, "cxk", "师傅!救我口牙!"));

list.add(new Practice(R.mipmap.liyue, "cxk1", "2333333"));

list.add(new Practice(R.mipmap.liyue, "cxk2", "[语音聊天]"));

return list;

}

}

}

```

注意:这里假设你已经在`res/layout`目录下创建了一个名为`activity_main.xml`的布局文件,并在其中定义了一个`ListView`组件。同时,你需要创建一个自定义的`ArrayAdapter`类,继承自`BaseAdapter`,用于处理数据和视图之间的绑定。

四、GridView网格形式显示

1. 准备工作:准备GridView每一个子项的视图布局。可以使用内置的布局,也可以用户自定义布局。

2. 创建Adapter(连接数据源和视图布局):

```java

//获取GridView控件

GridView gv_practice = findViewById(R.id.gv_practice);

//获取数据源

List list = Practice.getPractice();

//创建Adapter

PracticeAdapter adapter = new PracticeAdapter(

TabPracticeActivity.this,

R.layout.item_practice, //子控件id

list

); //为GridView绑定Adapter

gv_practice.setAdapter(adapter);

```

3. 为GridView绑定事件监听器:使用匿名内部类的方式绑定事件监听器。

```java

//为GridView绑定事件监听器

gv_practice.setOnItemClickListener(new AdapterView.OnItemClickListener() {

@Override

public void onItemClick(AdapterView parent, View view, int position, long id) {

Toast.makeText(TabPracticeActivity.this, list.get(position).getNickName(), Toast.LENGTH_SHORT).show();

}

});

```

在这里,我们可以直接将上面的ListView的Adapter绑定给GridView,即使用同一份数据对应不同的视图。首先,需要将布局文件中的ListView替换为GridView:

```xml

android:layout_width="match_parent"

android:layout_height="match_parent">

android:id="@+id/gv_product"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:horizontalSpacing="2dp"

android:verticalSpacing="2dp"

android:numColumns="2"/>

```

接下来,我们需要将步骤三和四中的ListView全部替换为GridView。具体操作如下:

1. 在原来的适配器代码中,修改getView()方法,使其适用于GridView。例如,如果原来的代码是这样的:

```java

@Override

public View getView(int position, View convertView, ViewGroup parent) {

...

}

```

需要修改为:

```java

@Override

public View getView(final int position, View convertView, ViewGroup parent) {

...

}

```

这样可以避免在循环中使用同一个视图。

2. 将原来适配器中的ViewHolder替换为GridViewHolder。首先创建一个新的类继承自BaseViewHolder,并添加一个ImageView控件用于显示图片:

```java

public class GridViewHolder extends BaseViewHolder {

public GridViewHolder(View itemView) {

super(itemView);

mImageView = (ImageView) itemView.findViewById(R.id.imageView);

}

}

```

然后在适配器中使用这个新的ViewHolder类:

```java

public class MyAdapter extends BaseAdapter {

...

@Override

public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

View view =LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);

return new GridViewHolder(view);

}

...

}

```

3. 最后,修改适配器的布局文件,将其从ListView改为GridView。例如,如果原来是这样的:

```xml

```

需要修改为:

```xml

```

五、Fragment和ViewPager2视图控件的使用

1. 什么是Fragment?

Fragment,即“片段”,是为了解决安卓应用运行在不同设备上尺寸不一致的问题而提出的。Fragment将屏幕分成若干组,进行模块化管理。可以将Fragment视为Activity界面的一个组成部分,一个Activity可以包含多个Fragment。

Fragment拥有自己的生命周期,可以接收并处理用户的事件。在Activity中,可以动态地添加、替换和移除某个Fragment。

2. ViewPager2

ViewPager2是Android Jetpack库中的一个组件,用于实现滑动切换页面的功能。与传统的ViewPager相比,ViewPager2提供了更好的性能和更多的功能。

以下是一个简单的使用ViewPager2的示例:

首先,在布局文件中添加ViewPager2控件:

```xml

android:id="@+id/view_pager"

android:layout_width="match_parent"

android:layout_height="match_parent" />

```

然后,创建一个Fragment列表,并为每个Fragment设置布局文件:

```java

List fragmentList = new ArrayList<>();

fragmentList.add(new FirstFragment());

fragmentList.add(new SecondFragment());

fragmentList.add(new ThirdFragment());

```

接下来,创建一个适配器类,继承自`RecyclerView.Adapter`,并实现相应的方法:

```java

public class ViewPager2Adapter extends RecyclerView.Adapter {

private List fragmentList;

private Context context;

public ViewPager2Adapter(Context context, List fragmentList) {

this.context = context;

this.fragmentList = fragmentList;

}

@NonNull

@Override

public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

return new ViewHolder(LayoutInflater.from(context).inflate(R.layout.fragment_item, parent, false));

}

@Override

public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

Fragment fragment = fragmentList.get(position);

holder.fragmentContainer.beginTransaction()

.replace(R.id.fragment_container, fragment)

.commit();

}

@Override

public int getItemCount() {

return fragmentList.size();

}

static class ViewHolder extends RecyclerView.ViewHolder {

LinearLayout fragmentContainer;

ViewHolder(@NonNull View itemView) {

super(itemView);

fragmentContainer = itemView.findViewById(R.id.fragment_container);

}

}

}

```

最后,在Activity或Fragment中初始化ViewPager2,并设置适配器:

1) 设计布局文件(TabLayout+ViewPager2):

首先,我们需要在项目的布局文件中添加TabLayout和ViewPager2组件。以下是一个简单的示例:

```xml

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity">

android:id="@+id/tab_layout"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

app:layout_constraintTop_toTopOf="parent"

app:layout_constraintStart_toStartOf="parent"

app:layout_constraintEnd_toEndOf="parent" />

android:id="@+id/view_pager"

android:layout_width="match_parent"

android:layout_height="0dp"

app:layout_constraintBottom_toBottomOf="parent"

app:layout_constraintTop_toBottomOf="@id/tab_layout" />

```

接下来,我们需要创建一个FragmentStateAdapter来管理Fragment的生命周期。以下是一个简单的示例:

```java

public class MyFragmentStateAdapter extends FragmentStateAdapter {

private List fragmentList;

private List titleList;

public MyFragmentStateAdapter(@NonNull FragmentActivity fragmentActivity, int viewPagerId, List fragmentList, List titleList) {

super(fragmentActivity);

this.fragmentList = fragmentList;

this.titleList = titleList;

}

@NonNull

@Override

public Fragment createFragment(int position) {

return fragmentList.get(position);

}

@Override

public int getItemCount() {

return fragmentList.size();

}

@Nullable

@Override

public CharSequence getPageTitle(int position) {

return titleList.get(position);

}

}

```

最后,在Activity中设置ViewPager2和TabLayout的适配器,并实现滑动切换功能。以下是一个简单的示例:

```java

public class MainActivity extends AppCompatActivity implements ViewPager2.OnPageChangeListener, TabLayout.OnTabSelectedListener {

private ViewPager2 viewPager;

private TabLayout tabLayout;

private MyFragmentStateAdapter adapter;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

viewPager = findViewById(R.id.view_pager);

tabLayout = findViewById(R.id.tab_layout);

initView();

}

private void initView() {

// 这里可以根据需要自定义Fragment和标题列表,然后创建MyFragmentStateAdapter实例并设置给viewPager2和tabLayout的适配器属性。以下是一个简单的示例:

List fragmentList = new ArrayList<>();

List titleList = new ArrayList<>();

fragmentList.add(new FirstFragment()); // 这里替换为你的Fragment实例名或类名,以及对应的标题字符串。可以添加多个Fragment。

titleList.add("第一个页面"); // 这里替换为你的标题字符串。可以添加多个标题。

adapter = new MyFragmentStateAdapter(this, R.id.view_pager, fragmentList, titleList); // 这里替换为你的ViewPager2的ID。如果使用其他ID,请相应地修改代码。

以下是重构后的代码,保持了原有的段落结构和格式:

```xml

android:layout_width="match_parent"

android:layout_height="match_parent">

android:id="@+id/vp_context"

android:layout_width="match_parent"

android:layout_height="match_parent">

android:id="@+id/tb_nav"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_alignParentBottom="true">

```

定义Fragment的item子布局(取名fragment_wechat)以及对应的Fragment如下(实际开发中由四个人分别定义):

1. fragment_wechat(微信界面)

2. fragment_contacts(通讯录界面)

3. fragment_discoveries(发现界面)

4. fragment_mine(我的界面)

首先,我们需要创建一个名为`WechatFragmentStateAdapter`的自定义适配器类,该类继承自`FragmentStateAdapter`,并重写其中的方法。然后,在`WechatFragment`中使用这个自定义适配器。

1. 创建自定义适配器类:

```java

public class WechatFragmentStateAdapter extends FragmentStateAdapter {

public WechatFragmentStateAdapter(@NonNull FragmentActivity fragmentActivity) {

super(fragmentActivity);

}

@NonNull

@Override

public Fragment createFragment(int position) {

return WechatFragment.newInstance();

}

@Override

public int getItemCount() {

// 这里返回你需要的item数量,例如:5个

return 5;

}

}

```

2. 在`WechatFragment`中使用自定义适配器:

```java

public class WechatFragment extends Fragment {

private static final String ARG_WECHAT_FRAGMENT_STATE_ADAPTER = "wechat_fragment_state_adapter";

public static WechatFragment newInstance() {

return new WechatFragment();

}

@Nullable

@Override

public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

// 从Bundle中获取自定义的适配器实例,如果不存在则创建一个新的实例

WechatFragmentStateAdapter adapter = (WechatFragmentStateAdapter) getArguments().getSerializable(ARG_WECHAT_FRAGMENT_STATE_ADAPTER);

if (adapter == null) {

adapter = new WechatFragmentStateAdapter(getParentFragment());

}

View view = inflater.inflate(R.layout.fragment_wechat, container, false);

// 将自定义的适配器设置给RecyclerView

// 这里需要确保你的RecyclerView使用的是LayoutManager为LinearLayoutManager或GridLayoutManager,以便正确显示子项的数量和位置

RecyclerView recyclerView = view.findViewById(R.id.recycler_view);

recyclerView.setLayoutManager(new GridLayoutManager(view.getContext(), getItemCount())); // 根据实际情况选择合适的LayoutManager

MyRecyclerViewAdapter myRecyclerViewAdapter = new MyRecyclerViewAdapter(adapter); // 注意这里的MyRecyclerViewAdapter应该替换为你实际使用的适配器类名

recyclerView.setAdapter(myRecyclerViewAdapter);

return view;

}

}

```

3. 在你的布局文件中添加一个RecyclerView:

```xml

android:id="@+id/recycler_view" />

```

要给ViewPager2设定适配器,首先需要创建一个自定义的适配器类,继承自`FragmentStateAdapter`,然后在Activity中实例化这个适配器类,并将其设置给ViewPager2。以下是具体的实现步骤和代码:

1. 创建一个自定义的适配器类,继承自`FragmentStateAdapter`,例如`WechatFragmentAdapter`:

```java

public class WechatFragmentAdapter extends FragmentStateAdapter {

private List fragmentList; //Fragment数据源,存放定义的四个Fragment

public WechatFragmentAdapter(@NonNull FragmentActivity fragmentActivity, @NonNull List fragmentList) {

super(fragmentActivity); //调用Activity,因为Fragment最终必须要和Activity联系,因此构造器必须实现;

this.fragmentList = fragmentList;

}

@NonNull

@Override

public Fragment createFragment(int position) {

return fragmentList.get(position);

}

@Override

public int getItemCount() {

return fragmentList.size();

}

}

```

2. 在Activity中实例化这个适配器类,并将其设置给ViewPager2:

```java

// ... 其他代码 ...

private void setupViewPager2() {

List fragmentList = new ArrayList<>();

// 将定义的四个Fragment添加到fragmentList中

// 例如:fragmentList.add(new FirstFragment());

// fragmentList.add(new SecondFragment());

// fragmentList.add(new ThirdFragment());

// fragmentList.add(new FourthFragment());

WechatFragmentAdapter adapter = new WechatFragmentAdapter(this, fragmentList);

vp2.setAdapter(adapter); // 将适配器设置给ViewPager2

}

// ... 其他代码 ...

```

首先,我们需要在activity中获取TabLayout和ViewPager2的实例。然后,创建一个Fragment数据源,包括四个Fragment:WechatFragment、ContractFragment、FindFragment和MineFragment。接着,创建一个适配器WechatFragmentAdapter,将fragmentList作为参数传入。最后,将ViewPager2绑定到适配器上,并使用TabLayoutMediator关联TabLayout和ViewPager2。

```java

// 获取activity中的控件

TabLayout tb_nav = findViewById(R.id.tb_nav);

ViewPager2 vp_context = findViewById(R.id.vp_context);

// 创建fragment数据源

List fragmentList = new ArrayList<>();

fragmentList.add(new WechatFragment());

fragmentList.add(new ContractFragment());

fragmentList.add(new FindFragment());

fragmentList.add(new MineFragment());

// 创建适配器

WechatFragmentAdapter adapter = new WechatFragmentAdapter(fragmentList, this);

// viewpager2绑定适配器

vp_context.setAdapter(adapter);

// 关联TabLayout与ViewPager2(使用TabLayoutMediator)

TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(tb_nav, vp_context, (tab, position) -> {

// 根据位置设置选中的tab

vp_context.setCurrentItem(position);

});

tabLayoutMediator.attach();

```

// 关联 TabLayout 和 ViewPager2

TabLayoutMediator mediator = new TabLayoutMediator(tb_nav, vp_context, new TabLayoutMediator.TabConfigurationStrategy() {

@Override

// 设置每个 tab 位置的属性(图标,名称等)

public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {

switch (position) {

case 0:

tab.setText("微信");

tab.setIcon(R.mipmap.message);

break;

case 1:

tab.setText("联系人");

tab.setIcon(R.mipmap.contract);

break;

case 2:

tab.setText("发现");

tab.setIcon(R.mipmap.find);

break;

case 3:

tab.setText("我的");

tab.setIcon(R.mipmap.mine);

break;

}

}

}); // 使效果生效

mediator.attach();

最终效果如下:

4 一些小优化

在最终效果中,我们发现底部导航与Fragment中的内容正好是对应的,但是我们并没有进行相关操作。实际上,Fragment的内容是按照加入fragmentList的顺序出现的,那么在设置每个tab位置的图标和名称时,我们可以直接按照顺序设置图标和名称。

首先定义两个List,分别存放名称和图标id,注意顺序必须一一对应:

```java

List tabNameList = new ArrayList<>();

tabNameList.add("微信");

tabNameList.add("联系人");

tabNameList.add("发现");

tabNameList.add("我的");

List tabImageList = new ArrayList<>();

tabImageList.add(R.mipmap.message);

tabImageList.add(R.mipmap.contract);

tabImageList.add(R.mipmap.find);

tabImageList.add(R.mipmap.mine);

```

然后在设置tab位置的属性时替换掉switch,这样就可以对代码进行优化:

要将TabLayout和ViewPager2关联起来,可以通过以下步骤实现:

1. 创建一个TabLayoutMediator实例,传入TabLayout、ViewPager2以及自定义的TabConfigurationStrategy。

2. 在TabConfigurationStrategy中,重写onConfigureTab方法,设置每个tab的位置属性(如图标、名称等)。

3. 调用attach()方法使效果生效。

以下是示例代码:

```java

// 创建TabLayoutMediator实例

TabLayoutMediator mediator = new TabLayoutMediator(tb_nav, vp_context, new TabLayoutMediator.TabConfigurationStrategy() {

@Override

// 设置每个tab位置的属性(图标,名称等)

public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {

// 替换掉switch,直接按顺序设置

tab.setText(tabNameList.get(position));

tab.setIcon(tabImageList.get(position));

}

});

// 使效果生效

mediator.attach();

```