Before two days want to be familiar with tablayout, so I made a particularly simple tablayout+viewpager+ Fragmet + recyclerView combination of small demo. It was pretty simple, but it still ran into a lot of problems.

Tablayout display title, viewPager implementation slide, fragment loading data, recyclerView display data.

  • Step1: introduce dependencies

implementation ‘com.android.support:appcompat-v7:xxx’ implementation ‘com.android.support:design:xxx’ implementation ‘com.android.support:recyclerview-v7:xxx’

  • Step2: introduce tabLayout into XML
<android.support.design.widget.TabLayout
Copy the code

In a Java file:

tabLayout = (TabLayout) findViewById(R.id.tab);
tabLayout.setupWithViewPager(viewPager);
Copy the code

MODE_FIXED: This mode can be used when the number of tabs is small and the entire screen is occupied. Tablayout. MODE_SCROLLABLE: This mode is used when there are too many tabs and the screen width is insufficient. The entire TabLayout can be slid left and right.

tabLayout.setTabMode(TabLayout.MODE_FIXED);
Copy the code
  • Step3: Then come the viewPager

XML is introduced into

 <android.support.v4.view.ViewPager
Copy the code

Java file

viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setAdapter(new FragmentAdapter(getSupportFragmentManager(), fragmentList));
Copy the code
  • Step4: fragments
public class MyFragment extends Fragment {
Copy the code

Classes that inherit from fragmentPagerAdapter don’t need to override so many methods and must have getItem(int) and getCount(). But I also added these two methods.

    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {}@Override
    public CharSequence getPageTitle(int position) {
        stringList.add(Pieces of "1");
        stringList.add("2 pieces");
        stringList.add("Three pieces");
        return stringList.get(position);
    }
Copy the code

To clarify, the first method overloads the method to prevent the fragment from being destroyed when the viewPager slides and the data needs to be reloaded. If the data in the viewpager is retrieved from the network, it will have to be retrieved from the network again with each swipe, which will affect performance.

After searching for the data and testing it, delete the super-.DestroyItem () directly in destroyItem. This will not reload the data. Of course, there are other ways to handle this situation, and if someone has tried and succeeded, you are welcome to comment on a better way.

The second reload method is to display the title of a tabLayout. There is a big hole in the title. Many examples on the web use addTab,setText directly in the main activity, but it is very easy to run into the problem of not displaying the title. . The solution is in the execution tablayout setUpWithViewPager. Then set by tablayout getTabAt (position). The setText (String) to set up.

However, now that you know how tabLayout works, you’ll be more likely to use getPageTitle directly inside your Fragment.

If you look at the source code, you can see that all added tabs have been removed, so the TAB and title added before this method will have no effect. TabLayout adds tabs and titles according to the number of adapters. So instead of adding tabs to the main acivity and setting the title, just use getPageTitle inside the fragment.

void populateFromPagerAdapter(a) {
        this.removeAllTabs();
        if (this.pagerAdapter ! =null) {
            int adapterCount = this.pagerAdapter.getCount();

            int curItem;
            for(curItem = 0; curItem < adapterCount; ++curItem) {
                this.addTab(this.newTab().setText(this.pagerAdapter.getPageTitle(curItem)), false);
            }

            if (this.viewPager ! =null && adapterCount > 0) {
                curItem = this.viewPager.getCurrentItem();
                if(curItem ! =this.getSelectedTabPosition() && curItem < this.getTabCount()) {
                    this.selectTab(this.getTabAt(curItem)); }}}}Copy the code

Note: Sometimes a Tablayout does not combine viewPager and Fragment, so you can only add tabs and headers to the main activity. Must pay attention to, add the title in tablayout setUpWithViewPager add behind () method.

viewPager.setAdapter(new FragmentAdapter(getSupportFragmentManager(), fragmentList));
Copy the code

FragmentList is the data source you need to prepare in advance

List<Fragment> fragmentList = new ArrayList<>();
fragmentList.add(new MyFragment());
        fragmentList.add(new MyFragment());
        fragmentList.add(new MyFragment());

Copy the code

These are your own custom fragment classes, including the associated XML. The fragment class does a lot of loading of XML views. The stuff inside the XML is what you want to display, in this case recyclerView. Fragment class, too long, make two pieces.

public class MyFragment extends Fragment {
    @Nullable
    List<String> data_top = new ArrayList<>();
    List<String> data_bottom = new ArrayList<>();
    List<String> data_new = new ArrayList<>();
    RecyclerView recyclerView;
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View fragment1 = inflater.inflate(R.layout.fragment_first, container, false);
        recyclerView = (RecyclerView) fragment1.findViewById(R.id.recycler_first);
        initRecycler();
        return fragment1;
    }
    public void initRecycler() {
        data_top.add("Layout Manager: Layout of the Item");
        data_top.add("Provide data for Item");
        data_top.add("Item Decoration: Divider between items");
        data_top.add("Item Animator: Add and remove Item animations");
        data_bottom.add("Follow Lei Feng's good example.");
        data_bottom.add("Follow Lei Feng's good example.");
        data_bottom.add("Follow Lei Feng's good example.");
        data_bottom.add("Follow Lei Feng's good example.");
        data_new.add("Stand firm and fight hard.");
        data_new.add("Stand firm and fight hard.");
        data_new.add("Stand firm and fight hard.");
        data_new.add("Stand firm and fight hard."); MainRecyclerAdapter mainRecyclerAdapter = new MainRecyclerAdapter(data_top, data_bottom, data_new, getContext()); recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); recyclerView.setAdapter(mainRecyclerAdapter); mainRecyclerAdapter.notifyDataSetChanged(); }}Copy the code

Hi, I see a new friend again. Come and RecyclerView. Introduce yourself to what you do

  • Step5: RecyclerView

If you want to display simple data in fragment, that’s fine, but if you want to display your data in RecyclerView, it’s not so easy. RecyclerView needs a data adapter of its own. All right, let’s build him one. Insert a complete file code.

public class MainRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { Context context; Public static enum TYPE_ENUM {IMAGE_ENUM, TEXT_ENUM } public static class TextHolder extends RecyclerView.ViewHolder { TextView text_top, text_bottom; ImageView icon; public TextHolder(@NonNull View itemView) { super(itemView); text_top = (TextView) itemView.findViewById(R.id.tv_top); text_bottom = (TextView) itemView.findViewById(R.id.tv_bottom); icon = (ImageView) itemView.findViewById(R.id.iv_icon); } } public static class ImageHolder extends RecyclerView.ViewHolder { TextView textTop; EditText textBottom; ImageView editIcon; public ImageHolder(@NonNull View itemView) { super(itemView); textTop = (TextView) itemView.findViewById(R.id.tv_top); textBottom = (EditText) itemView.findViewById(R.id.tv_bottom); editIcon = (ImageView) itemView.findViewById(R.id.iv_image_left); } } List<String> mDatas_top = new ArrayList<>(); List<String> mData_bottom = new ArrayList<>(); List<String> mData_new = new ArrayList<>(); public MainRecyclerAdapter(List<String> mDatas_top, List<String> mData_bottom, List<String> mData_new, Context context) { this.mDatas_top = mDatas_top; this.mData_bottom = mData_bottom; this.mData_new = mData_new; this.context = context; Override public int getItemViewType(int position) {returnposition % 2 == 0 ? TYPE_ENUM.IMAGE_ENUM.ordinal() : TYPE_ENUM.TEXT_ENUM.ordinal(); } //getItemViewType returns the int I of the getItemViewType method, so the type of adapter @nonnull @override public recyclerView.viewholder is used onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {if (i == TYPE_ENUM.IMAGE_ENUM.ordinal()) {
            return new ImageHolder(LayoutInflater.from(context).inflate(R.layout.recycleritemnew, viewGroup, false));
        } else {
            return new TextHolder(LayoutInflater.from(context).inflate(R.layout.recycler_item, viewGroup, false)); @override public void onBindViewHolder(@nonnull recyclerView. ViewHolder holder, int I) {if (holder instanceof ImageHolder) {
            //((ImageHolder) holder).textTop.setText(mData_new.get(i));
            ((ImageHolder) holder).textBottom.setText("haoya");
            ((ImageHolder) holder).editIcon.setBackgroundResource(R.mipmap.ic_launcher_round);
        } else {
            ((TextHolder) holder).text_top.setText(mDatas_top.get(i));
            ((TextHolder) holder).text_bottom.setText(mData_bottom.get(i));
            ((TextHolder) holder).icon.setBackgroundResource(R.mipmap.ic_launcher);
            //holder.itemView.setBackgroundResource(R.mipmap.ic_launcher);
        }
    }

    @Override
    public int getItemCount() {
        returnmDatas_top.size(); }}Copy the code

The code is a little long. First do not say different types of holder, first say a single type, how to use RecyclerView to achieve. RecyclerView implementation is a little bit more complicated than the listView we are familiar with. Ok, now let’s talk about each part.

(1) First write down what layout you want for each line of the list. Mine is the picture on the right side of the top and bottom words, which is fixed. This word is not textured, see you need.

(2) In general, you need to load things from XML in Java files, so who does that in RecyclerView? Create a view for holder.

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        if (i == TYPE_ENUM.IMAGE_ENUM.ordinal()) {
            return new ImageHolder(LayoutInflater.from(context).inflate(R.layout.recycleritemnew, viewGroup, false));
        } else {
            return new TextHolder(LayoutInflater.from(context).inflate(R.layout.recycler_item, viewGroup, false)); }}Copy the code

(3) So once it’s created, it’s bound, right? Yeah, yeah, here

   @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int i) {
        if (holder instanceof ImageHolder) {
            //((ImageHolder) holder).textTop.setText(mData_new.get(i));
            ((ImageHolder) holder).textBottom.setText("haoya");
            ((ImageHolder) holder).editIcon.setBackgroundResource(R.mipmap.ic_launcher_round);
        } else{ ((TextHolder) holder).text_top.setText(mDatas_top.get(i)); ((TextHolder) holder).text_bottom.setText(mData_bottom.get(i)); ((TextHolder) holder).icon.setBackgroundResource(R.mipmap.ic_launcher); //holder.itemView.setBackgroundResource(R.mipmap.ic_launcher); }}Copy the code

Depending on the controls in your XML. If it’s a type, I’ll just do it like this code, for example, you know what it is

holder.itemView.setBackgroundResource(R.mipmap.ic_launcher);
Copy the code

What else is there? Let’s see, oh, where does the data come from when you bind the view, yeah, from the constructor. MainRecyclerAdapter = new MainRecyclerAdapter(data_top, data_bottom, data_new, getContext()); So again,

List<String> mDatas_top = new ArrayList<>();
    List<String> mData_bottom = new ArrayList<>();
    List<String> mData_new = new ArrayList<>();

    public MainRecyclerAdapter(List<String> mDatas_top, List<String> mData_bottom, List<String> mData_new, Context context) {
        this.mDatas_top = mDatas_top;
        this.mData_bottom = mData_bottom;
        this.mData_new = mData_new;
        this.context = context;
    }
Copy the code

And then finally,

((TextHolder) holder).text_top.setText(mDatas_top.get(i));
            ((TextHolder) holder).text_bottom.setText(mData_bottom.get(i));
            ((TextHolder) holder).icon.setBackgroundResource(R.mipmap.ic_launcher);
            
Copy the code

Wow, that’s a long article. I think it’s over. Yeah, well, we can’t forget that he exists. He really has a sense of existence. Findviewbyid is a class that inherits from viewholder and lives inside the Adapter class to place the XML control findViewById.

public static class TextHolder extends RecyclerView.ViewHolder { TextView text_top, text_bottom; ImageView icon; public TextHolder(@NonNull View itemView) { super(itemView); text_top = (TextView) itemView.findViewById(R.id.tv_top); text_bottom = (TextView) itemView.findViewById(R.id.tv_bottom); icon = (ImageView) itemView.findViewById(R.id.iv_icon); }}Copy the code

There’s a point where, if it’s just a holder, the frame part could be mainRecyclerAdapter.vh –VH is your inner class name.

public class MainRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
Copy the code

My personal understanding of this adapter, first of all, it inherited recyclerView. adapter, implemented several necessary methods, and added an inner class

Holder’s words, I think, are a pocket that wraps around the view control. Oncreateviewholder creates the holder. Onbindviewholder refers to passing the data source required by the control to the corresponding control.

May not understand accurately, I hope you don’t hesitate to comment.

Ok, so that’s it for a single type adapter. Single type means that RecyclerView from beginning to end, the position type of the controls is the same, the same style. But sometimes, there are requirements that require a different type. Another parent method, getItemViewType(int Position), is used to set the type of Adapter required for this line according to position, as detailed in the complete code above. There are notes here. I believe you can understand ~

The end!

The authors introduce

  • Yang Xiaohua: Android development intern of Guangzhou Reed Technology APP Team

Push the information

  • We are recruiting partners, interested partners can send your resume to [email protected], note: from the nuggets community
  • For details, please click here –> Guangzhou Reed Information Technology