EasyDemo*ViewPager+Fragment Implementation of on Github

Keywords: Android Fragment ButterKnife Java

Source code: https://github.com/Way123Ne/android/tree/master/SlideFragment

Preface

Wechat's sliding switching has won unanimous praise. In the process of our development, we often imitate the navigation effect of Wechat.

  • First look at the rendering.

The effect is fairly good, you can slide switch and click switch, the Wechat interface shows data with listview, the address book interface shows data with recycler view, in the next analysis with you one by one.

  • activity_main.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">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/blue">

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="WeChat"
            android:textColor="@android:color/white"
            android:textSize="20sp"/>
    </RelativeLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/mainViewPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginTop="1dp"
        android:background="@android:color/white"
        android:baselineAligned="false"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:paddingBottom="5dp"
        android:paddingTop="5dp">

        <TextView
            android:id="@+id/item_weixin"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center_horizontal|center_vertical"
            android:text="WeChat"
            android:textColor="@drawable/main_tab_text_color"
            android:textSize="15dp"/>

        <TextView
            android:id="@+id/item_tongxunlu"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center_horizontal|center_vertical"
            android:text="Mail list"
            android:textColor="@drawable/main_tab_text_color"
            android:textSize="15dp"/>

        <TextView
            android:id="@+id/item_faxian"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center_horizontal|center_vertical"
            android:text="find"
            android:textColor="@drawable/main_tab_text_color"
            android:textSize="15dp"/>

        <TextView
            android:id="@+id/item_me"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center_horizontal|center_vertical"
            android:text="I"
            android:textColor="@drawable/main_tab_text_color"
            android:textSize="15dp"/>
    </LinearLayout>

</LinearLayout>

The main layout is clear, with a vertical Linear Layout on the outermost layer, which is lined with Title bars, ViewPager, and navigation bars in turn.

  • MainActivity.class
package com.cc.testdemo;

import android.graphics.Color;
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.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private TextView title, item_weixin, item_tongxunlu, item_faxian, item_me;
    private ViewPager vp;
    private OneFragment oneFragment;
    private TwoFragment twoFragment;
    private ThreeFragment threeFragment;
    private FouthFragment fouthFragmen;
    private List<Fragment> mFragmentList = new ArrayList<Fragment>();
    private FragmentAdapter mFragmentAdapter;

    String[] titles = new String[]{"WeChat", "Mail list", "find", "I"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //Remove toolbars
        getSupportActionBar().hide();
        setContentView(R.layout.activity_main);
        initViews();

        mFragmentAdapter = new FragmentAdapter(this.getSupportFragmentManager(), mFragmentList);
        vp.setOffscreenPageLimit(4);//ViewPager cache is 4 frames
        vp.setAdapter(mFragmentAdapter);
        vp.setCurrentItem(0);//Initially set ViewPager to select the first frame
        item_weixin.setTextColor(Color.parseColor("#66CDAA"));

        //ViewPager's listening events
        vp.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                /*This method is called when the page is selected*/
                title.setText(titles[position]);
                changeTextColor(position);
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                /*This method is called when the state changes, where arg0 has three states (0, 1, 2).
                arg0 ==1 The time is slipping.
                arg0==2 The time implies that the slide is over.
                arg0==0 Time implies that nothing has been done.*/
            }
        });
    }

    /**
     * Initialize Layout View
     */
    private void initViews() {
        title = (TextView) findViewById(R.id.title);
        item_weixin = (TextView) findViewById(R.id.item_weixin);
        item_tongxunlu = (TextView) findViewById(R.id.item_tongxunlu);
        item_faxian = (TextView) findViewById(R.id.item_faxian);
        item_me = (TextView) findViewById(R.id.item_me);

        item_weixin.setOnClickListener(this);
        item_tongxunlu.setOnClickListener(this);
        item_faxian.setOnClickListener(this);
        item_me.setOnClickListener(this);

        vp = (ViewPager) findViewById(R.id.mainViewPager);
        oneFragment = new OneFragment();
        twoFragment = new TwoFragment();
        threeFragment = new ThreeFragment();
        fouthFragmen = new FouthFragment();
        //Add data to FragmentList
        mFragmentList.add(oneFragment);
        mFragmentList.add(twoFragment);
        mFragmentList.add(threeFragment);
        mFragmentList.add(fouthFragmen);
    }

    /**
     * Click on the bottom Text to dynamically modify the contents of the ViewPager
     */
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.item_weixin:
                vp.setCurrentItem(0, true);
                break;
            case R.id.item_tongxunlu:
                vp.setCurrentItem(1, true);
                break;
            case R.id.item_faxian:
                vp.setCurrentItem(2, true);
                break;
            case R.id.item_me:
                vp.setCurrentItem(3, true);
                break;
        }
    }


    public class FragmentAdapter extends FragmentPagerAdapter {

        List<Fragment> fragmentList = new ArrayList<Fragment>();

        public FragmentAdapter(FragmentManager fm, List<Fragment> fragmentList) {
            super(fm);
            this.fragmentList = fragmentList;
        }

        @Override
        public Fragment getItem(int position) {
            return fragmentList.get(position);
        }

        @Override
        public int getCount() {
            return fragmentList.size();
        }

    }

    /*
     *Modify the color of the bottom navigation Text by sliding ViewPager
     */
    private void changeTextColor(int position) {
        if (position == 0) {
            item_weixin.setTextColor(Color.parseColor("#66CDAA"));
            item_tongxunlu.setTextColor(Color.parseColor("#000000"));
            item_faxian.setTextColor(Color.parseColor("#000000"));
            item_me.setTextColor(Color.parseColor("#000000"));
        } else if (position == 1) {
            item_tongxunlu.setTextColor(Color.parseColor("#66CDAA"));
            item_weixin.setTextColor(Color.parseColor("#000000"));
            item_faxian.setTextColor(Color.parseColor("#000000"));
            item_me.setTextColor(Color.parseColor("#000000"));
        } else if (position == 2) {
            item_faxian.setTextColor(Color.parseColor("#66CDAA"));
            item_weixin.setTextColor(Color.parseColor("#000000"));
            item_tongxunlu.setTextColor(Color.parseColor("#000000"));
            item_me.setTextColor(Color.parseColor("#000000"));
        } else if (position == 3) {
            item_me.setTextColor(Color.parseColor("#66CDAA"));
            item_weixin.setTextColor(Color.parseColor("#000000"));
            item_tongxunlu.setTextColor(Color.parseColor("#000000"));
            item_faxian.setTextColor(Color.parseColor("#000000"));
        }
    }
}

MainActivity.class mainly deals with the logical processing of sliding switching. After switching, the font color of navigation menu is switched. The annotations on the code are clear, so there is no more explanation.

  • Fragement
package com.cc.testdemo;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class FouthFragment extends Fragment {
    public FouthFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_fouth, container, false);
    }
}
  •  
  • fragment.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             tools:context=".FouthFragment">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="'I'Interface"
        android:textSize="25sp"/>
</FrameLayout>
  •  

There are four fragments in it. Like the code, there is only one TextView in fragment. The above code can realize sliding switch and click switch.

  • The effect of the above code is as follows:

Okay, now let's add data to the list view and recycler view, respectively. Recycyler view is a control that Google pushes instead of listview.

  • The Onefragment page is displayed with Listview:
    Modified Onefragment.xml code:
package com.cc.testdemo;

import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;

public class OneFragment extends Fragment {


    @BindView(R.id.lv)
    ListView lv;
    @BindView(R.id.srl)
    SwipeRefreshLayout mSwipeRefreshLayout;

    private List<String> stringList;
    private ArrayAdapter lvAdapter;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_one, container, false);
        ButterKnife.bind(this, view);
        initData();
        return view;
    }

    private void initData() {
        stringList = new ArrayList<String>();
        for (int i = 0; i < 20; i++) {
            stringList.add(String.valueOf(i));
        }
        lvAdapter = new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_1, stringList);
        lv.setAdapter(lvAdapter);

        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                Toast.makeText(getActivity(), stringList.get(i).toString(), Toast.LENGTH_SHORT).show();
            }
        });


        lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
                Toast.makeText(getActivity(), "long click:" + stringList.get(i).toString(), Toast.LENGTH_SHORT).show();
                return true;
            }
        });


        //Initialize drop-down control color
        mSwipeRefreshLayout.setColorSchemeResources(android.R.color.holo_blue_bright, android.R.color.holo_green_light,
                android.R.color.holo_orange_light, android.R.color.holo_red_light);

        mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                new AsyncTask<Void, Void, Void>() {

                    @Override
                    protected Void doInBackground(Void... voids) {
                        SystemClock.sleep(2000);
                        return null;
                    }

                    @Override
                    protected void onPostExecute(Void aVoid) {
                        Toast.makeText(getActivity(), "Drop-down Refresh Success", Toast.LENGTH_SHORT).show();
                        mSwipeRefreshLayout.setRefreshing(false);
                    }
                }.execute();
            }
        });
    }
}

The code in One Fragment is to show the simulated data with Listview, which has a swipeRefreshLayout drop-down refresh control on the outer layer.

  • fragment_one.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             tools:context="com.cc.testdemo.OneFragment">

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/srl"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ListView
            android:id="@+id/lv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"></ListView>

    </android.support.v4.widget.SwipeRefreshLayout>

</FrameLayout>

The effect diagram of One Fragment:

Now let's look at the key recycler view instead of listview to display data.

Use of RecyclerView

RecyclerView has been around for some time. I believe you are no stranger to it. You can use it by importing support-v7.  
According to the official introduction, the control is used to display a large number of data sets in a limited window. In fact, we are not unfamiliar with the control of this function, such as ListView, GridView.  
So why do you need controls like RecyclerView with ListView and GridView? Overall, RecyclerView architecture provides a plug-in experience, highly decoupled, exceptionally flexible, and achieves amazing results by setting up different Layout Managers, ItemDecoration, and ItemAnimator it provides.

If you want to control how it is displayed, use Layout Manager
If you want to control the interval between Items (which can be plotted), please use ItemDecoration.
If you want to control the animation of adding or deleting Item, please use ItemAnimator.

For detailed use, please refer to: http://blog.csdn.net/lmj623565791/article/details/45059587

Now let's use the TwoFragment page to display the data using recyclerview:

TwoFragment.class code:

package com.cc.testdemo;


import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;

public class TwoFragment extends Fragment implements MyRecyclerViewOnclickInterface {


    @BindView(R.id.id_recyclerview)
    RecyclerView mRecyclerview;

    private MyRecyclerViewAdapter mAdapter;
    private List<String> stringList;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_two, container, false);
        ButterKnife.bind(this, view);
        initData();
        return view;
    }

    private void initData() {
        stringList = new ArrayList<String>();
        for (int i = 0; i < 20; i++) {
            stringList.add(String.valueOf(i));
        }
        mAdapter = new MyRecyclerViewAdapter(getActivity(), stringList);
        //Setting up Layout Manager
        mRecyclerview.setLayoutManager(new LinearLayoutManager(getActivity()));
        //Setting up adapter
        mRecyclerview.setAdapter(mAdapter);
        //Adding partition lines
        mRecyclerview.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
        mAdapter.setOnItemClickLitener(this);
    }

    @Override
    public void onItemClick(View view, int position) {
        Toast.makeText(getActivity(), stringList.get(position), Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onItemLongClick(View view, int position) {
        Toast.makeText(getActivity(), "onItemLongClick" + stringList.get(position), Toast.LENGTH_SHORT).show();
    }
}
  • fragment_two.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             tools:context="com.cc.testdemo.TwoFragment">

    <!-- TODO: Update blank fragment layout -->

    <android.support.v7.widget.RecyclerView
        android:id="@+id/id_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</FrameLayout>
  • MyRecyclerViewAdapter
package com.cc.testdemo;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.List;

/**
 * Created by CC on 2016/12/27.
 */
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder> {


    private Context context;
    private List<String> mDatas;

    private MyRecyclerViewOnclickInterface mOnItemClickLitener;

    public void setOnItemClickLitener(MyRecyclerViewOnclickInterface mOnItemClickLitener) {
        this.mOnItemClickLitener = mOnItemClickLitener;
    }

    public MyRecyclerViewAdapter(Context context, List<String> mDatas) {
        this.context = context;
        this.mDatas = mDatas;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        MyViewHolder holder = new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.recyclerview_item, parent, false));
        return holder;
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, int position) {
        holder.tv.setText(mDatas.get(position));
        // If a callback is set, click events are set
        if (mOnItemClickLitener != null) {
            //Click monitor
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int pos = holder.getLayoutPosition();
                    mOnItemClickLitener.onItemClick(holder.itemView, pos);
                }
            });

            //Long press monitoring
            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    int pos = holder.getLayoutPosition();
                    mOnItemClickLitener.onItemLongClick(holder.itemView, pos);
                    //Returning true allows long press events to be consumed and avoids starting clicks
                    return true;
                }
            });
        }

    }

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

    class MyViewHolder extends RecyclerView.ViewHolder {

        TextView tv;

        public MyViewHolder(View view) {
            super(view);
            tv = (TextView) view.findViewById(R.id.tv);
        }
    }
}
  • MyRecyclerViewOnclickInterface
package com.cc.testdemo;

import android.view.View;

/**
 * Created by CC on 2016/12/27.
 */
public interface MyRecyclerViewOnclickInterface {

    void onItemClick(View view, int position);
    void onItemLongClick(View view, int position);
}

MyRecyclerViewOnclickInterface initializes the interface method. Since recyclerview does not implement click processing for the time being, it can only add callbacks manually.

  • DividerItemDecoration
package com.cc.testdemo;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;

/**
 * This class is from the v7 samples of the Android SDK. It's not by me!
 * <p>
 * See the license above for details.
 */
public class DividerItemDecoration extends RecyclerView.ItemDecoration {

    private static final int[] ATTRS = new int[]{
            android.R.attr.listDivider
    };

    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;

    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;

    private Drawable mDivider;

    private int mOrientation;

    public DividerItemDecoration(Context context, int orientation) {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
        setOrientation(orientation);
    }

    public void setOrientation(int orientation) {
        if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
            throw new IllegalArgumentException("invalid orientation");
        }
        mOrientation = orientation;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent) {
//        Log.v("recyclerview - itemdecoration", "onDraw()");

        if (mOrientation == VERTICAL_LIST) {
            drawVertical(c, parent);
        } else {
            drawHorizontal(c, parent);
        }

    }


    public void drawVertical(Canvas c, RecyclerView parent) {
        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(parent.getContext());
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    public void drawHorizontal(Canvas c, RecyclerView parent) {
        final int top = parent.getPaddingTop();
        final int bottom = parent.getHeight() - parent.getPaddingBottom();

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
        if (mOrientation == VERTICAL_LIST) {
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        } else {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        }
    }
}

Divider ItemDecoration is a good implementation of Recycler View adding splitters (when using Layout Manager as Linear Layout Manager).

Posted by candice on Fri, 04 Jan 2019 11:33:09 -0800