目录:
一、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 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 public PracticeAdapter() {} //构造器 public PracticeAdapter(Context context, Integer layoutId, 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 ArrayAdapter 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 List 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 //创建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.add(new FirstFragment()); fragmentList.add(new SecondFragment()); fragmentList.add(new ThirdFragment()); ``` 接下来,创建一个适配器类,继承自`RecyclerView.Adapter`,并实现相应的方法: ```java public class ViewPager2Adapter extends RecyclerView.Adapter private List private Context context; public ViewPager2Adapter(Context context, List 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 private List public MyFragmentStateAdapter(@NonNull FragmentActivity fragmentActivity, int viewPagerId, List 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 List 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 public WechatFragmentAdapter(@NonNull FragmentActivity fragmentActivity, @NonNull List 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 // 将定义的四个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.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.add("微信"); tabNameList.add("联系人"); tabNameList.add("发现"); tabNameList.add("我的"); List 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(); ```