当一个页面有3个Tab,可以滑动切换,自然想到了使用ViewPager+Fragment实现切换,如果每个Tab的页面都一致,只是请求接口的时候参数不一样的话,就自然会想到在Fragment实现动态加载数据。说的很简单,但是实际操作之后发现有很多的坑啊,各种问题,不能正常加载,或者页面没有显示等情况,现在记录一下,以免日后遇到相同的问题。
在Fragment中设置:
第一步:需要在Fragment进行实例化
主要是统一Fragment的实例化工作。如果Fragment需要外部传递参数,在此函数中要构造相关参数,这一步是必须的
public static MartialMoreFragment newInstance(String categoryArm) { MartialMoreFragment fragment = new MartialMoreFragment(); Bundle bundle = new Bundle(); bundle.putString("category", categoryArm); fragment.setArguments(bundle); return fragment; }
第二步:在Fragment中参数的获取
一要在onCreate方法获取参数。我写在了onCreateView中获取参数,但是看到网上说在onCreate方法中比较好,而onCreateView方法在某些状态下并不会被调用,导致数据丢失。
@Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle args = getArguments(); if (args != null) { this.category = args.getString("category"); } LoggerUtil.i(TAG, "onCreate--category--->" + category); }
第三步:在Fragment中参数的更新
更新Fragment内部成员变量的同时也要更新bundleArgs参数中的值。此步骤要和ViewPager适配器配合使用,实现Fragment动态刷新。这一步很关键,当滑动或者点击切换的时候就需要参数的更新,重新请求数据,否则就没有意义啦。
public void updateArguments(String categoryArm) { this.category = categoryArm; Bundle bundleArgs = getArguments(); if (bundleArgs != null) { bundleArgs.putString("category", categoryArm); } LoggerUtil.i(TAG, "updateArguments--category--->" + category); }
在ViewPager的适配器FragmentPagerAdapter中设置:
第一步:实现getItem方法
返回具体Fragment,并且初始化Fragment需要的参数,调用Fragment的newInstance()方法
@Override public Fragment getItem(int position) { return MartialMoreFragment.newInstance(categorys[position]); }
第二步:实现instantiateItem方法
如果需要动态刷新数据,就需要此方法,并且仅能在此方法里,不能是getItem。否则调用notifyDataSetChanged无效。
@Override public Object instantiateItem(ViewGroup container, final int position) { MartialMoreFragment fragment = (MartialMoreFragment) super.instantiateItem(container, position); fragment.updateArguments(categorys[position]); LoggerUtil.i("MartialMoreNoticeFragme","instantiateItem-->position-->"+position); return fragment; }第三步:实现getItemPosition方法
返回PagerAdapter.POSITION_NONE保证调用notifyDataSetChanged刷新Fragment。
@Override public int getItemPosition(Object object) { return PagerAdapter.POSITION_NONE; }第四步:也要实现ViewPager切换监听 OnPageChangeListener 方法
下面附上整体的Activity里面的代码,需要的话可以复制,保留自己需要的功能即可。
1.MartialMoreActivity:
import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView;
public class MartialMoreActivity extends BaseActivity implements View.OnClickListener { private ImageView img_martial_more_back; private TextView[] textViews; private TextView[] textViewLines; private ViewPager viewPager_martial; private String[] categorys = new String[]{"notice", "activity", "honor"}; private String martialName; private TextView tv_title_name; @Override public int getContentView() { return R.layout.activity_martial_more; } @Override public void initViews(Bundle savedInstanceState) { martialName=getIntent().getStringExtra("martialName"); tv_title_name=(TextView)findViewById(R.id.tv_title_name); img_martial_more_back = (ImageView) findViewById(R.id.img_martial_more_back); viewPager_martial = (ViewPager) findViewById(R.id.viewPager_martial); tv_title_name.setText(martialName); setTextviews(); setTextviewLines(); img_martial_more_back.setOnClickListener(this); NewsFragmentPagerAdapter mAdapetr = new NewsFragmentPagerAdapter(getSupportFragmentManager()); viewPager_martial.setAdapter(mAdapetr); viewPager_martial.addOnPageChangeListener(pageListener); viewPager_martial.setCurrentItem(0);//设置当前页数(页面返回时,可以设置页数) } @Override public void initDatas() { } @Override public void onClick(View view) { switch (view.getId()) { case R.id.img_martial_more_back: MartialMoreActivity.this.finish(); break; } } public class NewsFragmentPagerAdapter extends FragmentPagerAdapter { NewsFragmentPagerAdapter(FragmentManager fm) { super(fm); } @Override public int getCount() { return categorys.length; } @Override public Fragment getItem(int position) { return MartialMoreFragment.newInstance(categorys[position]); } @Override public int getItemPosition(Object object) { return PagerAdapter.POSITION_NONE; } @Override public Object instantiateItem(ViewGroup container, final int position) { MartialMoreFragment fragment = (MartialMoreFragment) super.instantiateItem(container, position); fragment.updateArguments(categorys[position]); LoggerUtil.i("MartialMoreNoticeFragme","instantiateItem-->position-->"+position); return fragment; } } /** * ViewPager切换监听方法 */ public ViewPager.OnPageChangeListener pageListener = new ViewPager.OnPageChangeListener() { @Override public void onPageScrollStateChanged(int arg0) { } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageSelected(int position) { resetlaybg(); textViews[position].setTextColor(getResources().getColor( R.color.a32DBC1)); textViewLines[position].setBackgroundColor(getResources().getColor(R.color.a32DBC1)); LoggerUtil.i("MartialMoreNoticeFragme","onPageSelected-->position-->"+position); } }; /** * 点击linerlayout实现切换fragment的效果 */ public void matialLayoutOnclick(View v) { // 每次点击都重置linearLayouts的背景、textViews字体颜色 switch (v.getId()) { case R.id.linear_notice: resetlaybg(); viewPager_martial.setCurrentItem(0); textViews[0].setTextColor(getResources().getColor( R.color.a32DBC1)); textViewLines[0].setBackgroundColor(getResources().getColor( R.color.a32DBC1)); break; case R.id.linear_activity: resetlaybg(); viewPager_martial.setCurrentItem(1); textViews[1].setTextColor(getResources().getColor( R.color.a32DBC1)); textViewLines[1].setBackgroundColor(getResources().getColor( R.color.a32DBC1)); break; case R.id.linear_honor: resetlaybg(); viewPager_martial.setCurrentItem(2); textViews[2].setTextColor(getResources().getColor( R.color.a32DBC1)); textViewLines[2].setBackgroundColor(getResources().getColor( R.color.a32DBC1)); break; } } /** * 初始化textview */ public void setTextviews() { textViews = new TextView[3]; textViews[0] = (TextView) findViewById(R.id.tv_notice); textViews[1] = (TextView) findViewById(R.id.tv_activity); textViews[2] = (TextView) findViewById(R.id.tv_honor); textViews[0].setTextColor(getResources() .getColor(R.color.a32DBC1)); } /** * 初始化textviewLine */ public void setTextviewLines() { textViewLines = new TextView[3]; textViewLines[0] = (TextView) findViewById(R.id.tv_notice_line); textViewLines[1] = (TextView) findViewById(R.id.tv_activity_line); textViewLines[2] = (TextView) findViewById(R.id.tv_honor_line); textViewLines[0].setBackgroundColor(getResources() .getColor(R.color.a32DBC1)); } /** * 重置textViews textViewLines */ public void resetlaybg() { for (int i = 0; i < 3; i++) { textViews[i].setTextColor(getResources().getColor(R.color.a999999)); textViewLines[i].setBackgroundColor(getResources().getColor(R.color.f4f4f4)); } } }
2.activity_martial_more.xml:
xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="@color/white" > <RelativeLayout android:layout_width="match_parent" android:layout_height="@dimen/dimen60"> <ImageView android:id="@+id/img_martial_more_back" android:layout_width="wrap_content" android:layout_height="match_parent" android:src="@drawable/study_play_back" android:layout_marginLeft="@dimen/dimen15" android:layout_centerVertical="true" /> <TextView android:id="@+id/tv_title_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/a252525" android:textSize="@dimen/size18" android:layout_centerInParent="true" /> RelativeLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <LinearLayout android:id="@+id/linear_notice" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" android:gravity="center" android:onClick="matialLayoutOnclick" > <TextView android:id="@+id/tv_notice" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="查看1" android:textSize="@dimen/size14" android:textColor="@color/a32DBC1" /> <TextView android:id="@+id/tv_notice_line" android:layout_width="match_parent" android:layout_height="@dimen/dimen2" android:background="@color/a32DBC1" android:layout_marginTop="@dimen/dimen13" /> LinearLayout> <LinearLayout android:id="@+id/linear_activity" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" android:gravity="center" android:onClick="matialLayoutOnclick" > <TextView android:id="@+id/tv_activity" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="查看2" android:textSize="@dimen/size14" android:textColor="@color/a999999" /> <TextView android:id="@+id/tv_activity_line" android:layout_width="match_parent" android:layout_height="@dimen/dimen2" android:background="@color/f4f4f4" android:layout_marginTop="@dimen/dimen13" /> LinearLayout> <LinearLayout android:id="@+id/linear_honor" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" android:gravity="center" android:onClick="matialLayoutOnclick" > <TextView android:id="@+id/tv_honor" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="查看3" android:textSize="@dimen/size14" android:textColor="@color/a999999" /> <TextView android:id="@+id/tv_honor_line" android:layout_width="match_parent" android:layout_height="@dimen/dimen2" android:background="@color/f4f4f4" android:layout_marginTop="@dimen/dimen13" /> LinearLayout> LinearLayout> <android.support.v4.view.ViewPager android:id="@+id/viewPager_martial" android:layout_width="match_parent" android:layout_height="match_parent" /> LinearLayout>
至此Activity已经完成,下面是Fragment的数据
在Fragmnet中使用了SwipeRefreshLayout+RecyclerView实现下拉刷新和上拉加载功能。
在Fragmnet服用需要注意的是:
1:有时候我发现数据会重复加载,解决这个问题可以使用以下方法:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //ViewPage + Fragment 防止Fragment 重复加载问题 if (view == null) { view = inflater.inflate(R.layout.activity_martial_more_fragment, container, false); initView();//初始化 } ViewGroup parent = (ViewGroup) view.getParent(); if (parent != null) { parent.removeView(view); } return view; }
2.因为在RecycleView还使用了GridView,之前遇到的问题是,当使用GridView展示图片的时候,如果没有全部加载完也就是有空白的时候,点击空白的地方不能跳转,这个问题可以查看
https://blog.csdn.net/juhua2012/article/details/79992280
以下是MartialMoreFragment中的代码:主要显示几个比较重要的
//1、Fragment的实例化 public static MartialMoreFragment newInstance(String categoryArm) { MartialMoreFragment fragment = new MartialMoreFragment(); Bundle bundle = new Bundle(); bundle.putString("category", categoryArm); fragment.setArguments(bundle); return fragment; } //2、Fragment参数的获取 @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle args = getArguments(); if (args != null) { this.category = args.getString("category"); } LoggerUtil.i(TAG, "onCreate--category--->" + category); } //3、Fragment参数的更新 public void updateArguments(String categoryArm) { this.category = categoryArm; Bundle bundleArgs = getArguments(); if (bundleArgs != null) { bundleArgs.putString("category", categoryArm); } LoggerUtil.i(TAG, "updateArguments--category--->" + category); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //ViewPage + Fragment 防止Fragment 重复加载问题 if (view == null) { view = inflater.inflate(R.layout.activity_martial_more_fragment, container, false); initView();//初始化 在这个方法进行获取控件等操作 } ViewGroup parent = (ViewGroup) view.getParent(); if (parent != null) { parent.removeView(view); } return view; }以上基本是自己在实现ViewPager+Fragmnet,在Fragment里面使用 SwipeRefreshLayout+RecyclerView遇到的问题,先记录到这里吧,自己觉得这种问题会经常遇到的,写个心得比较好,好记性不如烂笔头。