版权声明:本文为博主原创文章,未经博主允许不得转载。https://blog.csdn.net/zhang45362613/article/details/89310688
最近遇到一个自定义频道的功能需求,网上有很多这样的demo,这里就不说了,我来说说在实现的时候遇到的坑。
问题:既然有了自定义频道,那么自定义频道完成后,肯定是需要动态的去改变这些频道的展示,我采用了TabLayout+ViewPager的组合进行展示。大致的效果如下,具体实现自己去找找吧(如有源码需求可以留言)
![部分效果演示.gif](http://upload-images.jianshu.io/upload_images/937851-2df50ff9833dd386.gif?imageMogr2/auto-orient/strip)
好了,言归正传。
首先展示一下主界面的xml代码吧
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="@+id/tablayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#E0E0E0"
app:tabIndicatorColor="@color/ind_red"
app:tabMode="fixed"
app:tabSelectedTextColor="@color/material_orange"
app:tabTextColor="@android:color/black"
app:tabIndicatorHeight="5dp"
app:tabTextAppearance="@style/TabStyle"
/>
<android.support.v4.view.ViewPager
android:id="@+id/tab_viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@android:color/white" />
</LinearLayout>
代码实现如下
注:ChannelEntity是频道的实例,只有id和name两个属性,实现get和set方法,这里就不展示代码了
//首先创建一个list集合来接收频道设置界面设定的频道信息
selecte_channel = (List<ChannelEntity>) getIntent().getSerializableExtra("list");;
tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
// vp_pager.setAdapter(new MorePagerAdapter(selecte_channel))
adapter = new MyViewPagerAdapter(getSupportFragmentManager(), selecte_channel);
vp_pager.setAdapter(adapter);
tabLayout.setupWithViewPager(vp_pager);
这里创建一个handler来接收改变fragment的消息,并改变页面
public class MyReciver extends Handler{
@Override
public void handleMessage(Message msg) {
// selecte_channel.remove(0);
selecte_channel.add(new ChannelEntity((long) 0, "新增频道"));//这里为了测试,动态增加一个频道
adapter.RefreshFragments(selecte_channel);
vp_pager.setCurrentItem(0);
tabLayout.scrollTo(0,0);//这里主要是在刷新后,tablayout会滚动,我这里强制到第一个
}
}
需要注意的是记得对myReciver进行实例化哦
最后就是重点的了,遇到了很多坑,各种数组越界等问题,或者tablayout刷新后,但是fragment页面不能及时刷新(将FragmentPagerAdapter改成FragmentStatePagerAdapter试试,因为前者是不再重复执行fragment的oncreate方法的)
public class MyViewPagerAdapter extends FragmentStatePagerAdapter {
private List<ChannelEntity> list = new ArrayList<>();
private List<Fragment> fragments = new ArrayList<>();
private FragmentManager fm;
public MyViewPagerAdapter(FragmentManager fm, List<ChannelEntity> data) {
super(fm);
this.fm = fm;
this.list = data;
this.fragments = new ArrayList<>();
initFragments();
// for (ChannelEntity entity : data){
// this.fragments.add(new TabFragment());
// }
}
@Override
public Fragment getItem(int position) {
return fragments.get(position);
}
@Override
public int getCount() {
return fragments.size();
}
@Override
public CharSequence getPageTitle(int position) {
return list.get(position).getName();
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
/**
* 根据频道信息,添加对应的页面
*/
public void initFragments(){
for (ChannelEntity entity : list){
Log.e("entity.getid", "getid = " + entity.getId());
Log.e("entity.getid", "getname = " + entity.getName());
if(!entity.getName().equals("频道0")){
fragments.add(new TabFragment());
}else {
fragments.add(new Fragment1());
}
}
}
/**
* 动态刷新数据后,刷新界面
**/
public void RefreshFragments(List<ChannelEntity> datalist){
//避免重复创建fragment
if(this.fragments != null){
FragmentTransaction ft = fm.beginTransaction();
for(Fragment f:this.fragments){
ft.remove(f);
}
ft.commit();
ft=null;
fm.executePendingTransactions();
}
this.list = datalist;
this.fragments = new ArrayList<>();
initFragments();
notifyDataSetChanged();
}
fragment1和tabfragment两个fragment都是一个简单的为了区分的页面,自己简单写吧。然后在调用的时候,发送消息到myReciver中触发刷新就可以了
写得不好,请见谅,如果不足请指正!
更正:https://blog.csdn.net/u012762986/article/details/79778727这个博文也是可以解决问题,一并推荐给大家