仿網易新聞分類刷新

最近做自己的一些小東西的時候,需要用到類似網易新聞的那種分類界面,就是上面一個tab選項卡,下面一個viewpager,可以滑動的,而且無論是滑動到哪一頁,都可以下拉刷新當前頁面。想了半天后,總算是實現了,以下是效果圖。


效果圖

仿網易新聞分類刷新

效果很簡單,就是一個可滑動的分類,並且每頁都可以下拉刷新,並獲取到對應的數據。

原理分析

界面分析
首先界面是由TabLayout+viewpager實現的,並且,viewpager的每個頁面是一個fragment,根據效果圖,我們可以清晰的知道viewpager每頁的fragment佈局都相同,所以,就可以使用一個fragment,那麼,問題來了,怎麼讓每頁顯示不同的數據呢,這也是我寫這篇博客的主要目的。

怎麼讓每頁顯示不同的數據
在給viewpager的設置的適配器肯定是要繼承FragmentPagerAdapter的,之後需要實現2個方法,一個getItem(),一個getCount(),我們來重點看看getItem()這個方法,該方法需要返回一個fragment,假設我們的列表fragment是TypeListFragment。

@Override
    public Fragment getItem(int position) {
        //這是錯誤的寫法
        return new TypeListFragment();
    }

如果按照以上方法,肯定是錯的,爲什麼呢,因爲返回的fragment是不可控的,那麼就不能控制他顯示什麼數據。所以,這裏我們需要利用一些小技巧了,首先考慮,如果按照以上寫法,每次切換頁面的時候,總會實例一個fragment,不行,當然不行。我們可以根據分類種類的數量知道到底需要多少個fragment,我們可以先把這些fragment放到一個倉庫裏,需要哪個的時候,再取哪個。

FragmentRepertory.java(fragment倉庫)

public class FragmentRepertory {

    public static final String[] titles = {"頭條", "精選", "娛樂", "熱點", "體育", "科技", "時尚", "歷史"};

    private ArrayList<TypeListFragment> datas = new ArrayList<>();

    private FragmentRepertory() {

        for (String title : titles) {
            TypeListFragment fragment = new TypeListFragment();
            Bundle bundle = new Bundle();
            bundle.putString("type", title);
            fragment.setArguments(bundle);
            datas.add(fragment);
        }

    }

    private static FragmentRepertory repertory;

    public static FragmentRepertory getInstance() {
        if (repertory == null) {
            repertory = new FragmentRepertory();
        }
        return repertory;
    }

    public ArrayList<TypeListFragment> getDatas() {
        return datas;
    }

}

考慮到倉庫只需要一個,所以對該類做了下簡單的單例處理,並且提供了獲取整個倉庫數據的getDatas()方法。

實現步驟

這部分代碼比較多,但都比較簡單,也可以直接看下面的總結,核心實現方法

1.界面實現,垂直線性佈局+TabLayout+Viewpager

MainActivity.java#onCreate方法

    TabLayout tablayout = (TabLayout) findViewById(R.id.tablayout);
    ViewPager viewpager = (ViewPager) findViewById(R.id.viewpager);

    tablayout.setupWithViewPager(viewpager);

    //設置tablayout爲可滑動模式,
    tablayout.setTabMode(TabLayout.MODE_SCROLLABLE);

    MyFragmentPagerAdapter pageradapter = new MyFragmentPagerAdapter(getSupportFragmentManager());

    viewpager.setAdapter(pageradapter);

MyFragmentPagerAdapter .java

public class MyFragmentPagerAdapter extends FragmentPagerAdapter {

    public MyFragmentPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        return FragmentRepertory.getInstance().getDatas().get(position);
    }

    @Override
    public int getCount() {
        return FragmentRepertory.titles.length;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return FragmentRepertory.titles[position];
    }
}

TypeListFragment.java
該類,佈局結構爲RecyclerView外面嵌套SwipeRefreshLayout,然後添加5條初始信息給recyclerview。

public class TypeListFragment extends Fragment {

    private SwipeRefreshLayout swipeRefreshLayout;

    private MyAdapter adapter;

    private String type;

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            swipeRefreshLayout.setRefreshing(false);
            adapter.notifyDataSetChanged();
        }
    };

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recyclerview);
        swipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe);

        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));

        adapter = new MyAdapter(getContext());

        Bundle args = getArguments();

        type = args.getString("type");

        ArrayList<String> datas = new ArrayList<>();

        for (int i = 0; i < 5; i++) {
            datas.add(type + " " + i);
        }

        adapter.setDatas(datas);
        recyclerView.setAdapter(adapter);

        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                adapter.addData(type + "新增的");
                adapter.addData(type + "新增的");
                handler.sendEmptyMessageDelayed(1, 2000);
            }
        });

    }

}

MyAdapter.java(RecyclerView的適配器)

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {

    private ArrayList<String> datas = new ArrayList<>();

    private LayoutInflater inflater;

    public MyAdapter(Context context) {
        inflater = LayoutInflater.from(context);
    }

    public void setDatas(ArrayList<String> datas) {
        this.datas = datas;
    }

    public void addData(String string) {
        datas.add(string);
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new ViewHolder(inflater.inflate(android.R.layout.simple_list_item_1, null));
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.textView.setText(datas.get(position));
    }

    @Override
    public int getItemCount() {
        return datas.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        private TextView textView;
        public ViewHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(android.R.id.text1);
        }
    }


}

總結

代碼部分沒什麼好講的,這裏總結一下,具體實現的方式:

  1. 需要一個倉庫來存放fragment
  2. 要給每個fragment設置參數
    for (String title : titles) {
            TypeListFragment fragment = new TypeListFragment();
            Bundle bundle = new Bundle();
            bundle.putString("type", title);
            fragment.setArguments(bundle);
            datas.add(fragment);
    }

獲取參數:

        Bundle args = getArguments();
        type = args.getString("type");

根據參數的不同顯示數據,順便做個假刷新。

源碼下載

發佈了45 篇原創文章 · 獲贊 82 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章