RecyclerView Multi-Layout Writing, "My" and "Personal Center" Page Classic Writing Demonstration

Keywords: Android github xml encoding

Effect:



There are still many scenes of dubu Bureau, such as "home page" and "my" page. In the early days, people usually assembled them, then began to customize ListView (Alipay's current home page or ListView), and then to RecyclerView later.

In fact, multi-layout is a routine, according to the type to introduce layout, this paper takes Recycler View as an example, with Base Recycler View Adapter Helper as a supplement to demonstrate the writing of multi-layout.


1. Adding dependencies

compile 'com.github.yechaoa:YUtils:2.0.6'
compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.34'

YUtils is a collection of rapid development tools that can be stamped with interest YUtils


2. main page

The main page is ViewPager + Bottom Navigation View

Just a little later. Skip straight to Step 3 if you don't want to see it.


Layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent"
    tools:context="com.yechaoa.multipleitempage.MainActivity">

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

    <android.support.design.widget.BottomNavigationView
        android:id="@+id/navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:background="?android:attr/windowBackground"
        app:menu="@menu/navigation" />

</LinearLayout>


Add Listener to associate the two

mViewPager.addOnPageChangeListener(mOnPageChangeListener); 
mNavigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
private ViewPager.OnPageChangeListener mOnPageChangeListener = new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            mNavigation.getMenu().getItem(position).setChecked(true);
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    };


    private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
            = new BottomNavigationView.OnNavigationItemSelectedListener() {

        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()) {
                case R.id.navigation_home:
                    mViewPager.setCurrentItem(0);
                    return true;
                case R.id.navigation_category:
                    mViewPager.setCurrentItem(1);
                    return true;
                case R.id.navigation_cart:
                    mViewPager.setCurrentItem(2);
                    return true;
                case R.id.navigation_my:
                    mViewPager.setCurrentItem(3);
                    return true;
            }
            return false;
        }
    };

When the ViewPager is selected, let the item of Bottom Navigation View be selected, and when the item of Bottom Navigation View is selected, let the ViewPager switch the page.


3.Fragment ("My" page)

Layout, SwipeRefreshLayout (drop-down refresh) nested RecyclerView:

<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/swipeRefreshLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

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


Initialize Data

private void initItemData() {
        itemDataList = new ArrayList<>();

        multipleItem = new MultipleItem(MultipleItem.TYPE_COUNT, 5);
        multipleItem.mString1 = "Collection";
        multipleItem.mString2 = "follow";
        itemDataList.add(multipleItem);

        multipleItem = new MultipleItem(MultipleItem.TYPE_ORDER_HEADER, 5);
        multipleItem.mString2 = "type2";
        itemDataList.add(multipleItem);

        for (int i = 0; i < 5; i++) {
            multipleItem = new MultipleItem(MultipleItem.TYPE_ORDER, 1);
            multipleItem.mString1 = "Pending payment";
            if (i % 2 == 0) {
                multipleItem.isShow = true;
                multipleItem.count = 6;
            } else {
                multipleItem.isShow = false;
                multipleItem.count = 0;
            }
            itemDataList.add(multipleItem);
        }

        multipleItem = new MultipleItem(MultipleItem.TYPE_BALANCE, 5);
        multipleItem.mString1 = "¥9999.00";
        itemDataList.add(multipleItem);

        multipleItem = new MultipleItem(MultipleItem.TYPE_TOOLS_HEADER, 5);
        multipleItem.mString1 = "type5";
        itemDataList.add(multipleItem);

        for (int i = 0; i < 5; i++) {
            multipleItem = new MultipleItem(MultipleItem.TYPE_TOOLS, 1);
            multipleItem.mString1 = "Use help";
            if (i % 2 == 0) {
                multipleItem.isShow = true;
                multipleItem.count = 100;
            } else {
                multipleItem.isShow = false;
                multipleItem.count = 0;
            }
            itemDataList.add(multipleItem);
        }
    }


Get id

mSwipeRefreshLayout = getActivity().findViewById(R.id.swipeRefreshLayout);
mRecyclerView = getActivity().findViewById(R.id.recyclerView);


Initialize SwipeRefreshLayout

private void initSwipeRefreshLayout() {
        mSwipeRefreshLayout.setColorSchemeResources(
                android.R.color.holo_blue_bright,
                android.R.color.holo_green_light,
                android.R.color.holo_orange_light);

        mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        multipleItemQuickAdapter.notifyDataSetChanged();
                        mSwipeRefreshLayout.setRefreshing(false);
                        YUtils.showToast("Refresh finish");
                    }
                }, 2000);
            }
        });
    }


Initialize RecyclerView

private void initRecyclerView() {
        GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), 5);
        mRecyclerView.setLayoutManager(gridLayoutManager);

        multipleItemQuickAdapter = new MultipleItemQuickAdapter(itemDataList);

        View headerView = getHeaderView(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                switch (view.getId()) {
                    case R.id.my_header_image:
                        YUtils.showToast("You clicked on the Avatar");
                        break;
                    case R.id.my_header_settings:
                        YUtils.showToast("You clicked Settings");
                        break;
                }
            }
        });

        multipleItemQuickAdapter.addHeaderView(headerView);

        mRecyclerView.setAdapter(multipleItemQuickAdapter);
    }


Add Header

private View getHeaderView(View.OnClickListener listener) {
        View headerView = getLayoutInflater().inflate(R.layout.layout_my_header, (ViewGroup) mRecyclerView.getParent(), false);

        CircleImageView myHeaderImage = headerView.findViewById(R.id.my_header_image);
        myHeaderImage.setImageResource(R.drawable.header_image);
        myHeaderImage.setOnClickListener(listener);

        TextView myHeaderName = headerView.findViewById(R.id.my_header_name);
        myHeaderName.setText("Name");

        TextView myHeaderMobile = headerView.findViewById(R.id.my_header_mobile);
        myHeaderMobile.setText("Cell-phone number");

        ImageView myHeaderSettings = headerView.findViewById(R.id.my_header_settings);
        myHeaderSettings.setOnClickListener(listener);

        return headerView;
    }


Initialize Listener

private void initListener() {
        multipleItemQuickAdapter.setSpanSizeLookup(new BaseQuickAdapter.SpanSizeLookup() {
            @Override
            public int getSpanSize(GridLayoutManager gridLayoutManager, int position) {
                return itemDataList.get(position).getSpanSize();
            }
        });

        multipleItemQuickAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {

                YUtils.showToast("The first  " + position);

                //You can add another layer of type judgment. Generally speaking, orders don't disappear as soon as they are ordered.
                if (itemDataList.get(position).getItemType() == MultipleItem.TYPE_TOOLS) {
                    if (itemDataList.get(position).isShow) {
                        itemDataList.get(position).isShow = false;
                        LogUtil.i("count  =  " + itemDataList.get(position).count);
                        multipleItemQuickAdapter.notifyItemChanged(position + 1);
                    } else
                        itemDataList.get(position).isShow = false;
                }

            }
        });

        multipleItemQuickAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
            @Override
            public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
                switch (view.getId()) {
                    case R.id.my_favorites:
                        YUtils.showToast("Collection");
                        break;
                    case R.id.my_bands:
                        YUtils.showToast("follow");
                        break;
                    case R.id.ll_my_order:
                        YUtils.showToast("All orders");
                        break;
                    case R.id.my_balance_btn:
                        YUtils.showToast("Immediate recharge");
                        break;
                }
            }
        });

    }

setSpanSizeLookup can be configured if you consider reusing item s in GridLayoutManager

setOnItemClickListener, item click event

setOnItemChildClickListener, sub-view click event in item

When item clicks, the corner sign (badge) disappears and then refreshes locally.


4.Bean

Entity classes must implement MultiItemEntity, and when setting data, itemType must be set for each data.

public class MultipleItem implements MultiItemEntity {

    public static final int TYPE_COUNT = 1;
    public static final int TYPE_ORDER_HEADER = 2;
    public static final int TYPE_ORDER = 3;
    public static final int TYPE_BALANCE = 4;
    public static final int TYPE_TOOLS_HEADER = 5;
    public static final int TYPE_TOOLS = 6;
    private int itemType;
    private int spanSize;

    public MultipleItem(int itemType, int spanSize) {
        this.itemType = itemType;
        this.spanSize = spanSize;
    }

    @Override
    public int getItemType() {
        return itemType;
    }

    public int getSpanSize() {
        return spanSize;
    }

    public void setSpanSize(int spanSize) {
        this.spanSize = spanSize;
    }


    public String mString1;

    public String mString2;

    public boolean isShow;

    public int count;

}


5.Adapter

The key to multiple layouts is in the Adapter, which returns different layouts according to type, then fills in data, processes events, and so on.

In construction, addItemType binds the relationship between type and layout

public class MultipleItemQuickAdapter extends BaseMultiItemQuickAdapter<MultipleItem, BaseViewHolder> {

    public MultipleItemQuickAdapter(List data) {
        super(data);
        addItemType(MultipleItem.TYPE_COUNT, R.layout.layout_my_count);
        addItemType(MultipleItem.TYPE_ORDER_HEADER, R.layout.layout_my_order_header);
        addItemType(MultipleItem.TYPE_ORDER, R.layout.layout_my_order);
        addItemType(MultipleItem.TYPE_BALANCE, R.layout.layout_my_balance);
        addItemType(MultipleItem.TYPE_TOOLS_HEADER, R.layout.layout_my_tools_header);
        addItemType(MultipleItem.TYPE_TOOLS, R.layout.layout_my_tools);
    }

    @Override
    protected void convert(BaseViewHolder helper, MultipleItem item) {
        switch (helper.getItemViewType()) {
            case MultipleItem.TYPE_COUNT:
                helper.setText(R.id.my_favorites, item.mString1).addOnClickListener(R.id.my_favorites);
                helper.setText(R.id.my_bands, item.mString2).addOnClickListener(R.id.my_bands);
                break;
            case MultipleItem.TYPE_ORDER_HEADER:
                helper.addOnClickListener(R.id.ll_my_order);
                break;
            case MultipleItem.TYPE_ORDER:
                helper.setImageDrawable(R.id.my_order_image, ContextCompat.getDrawable(mContext, R.drawable.ic_launcher));
                helper.setText(R.id.my_order_name, item.mString1);
                if (item.isShow) {
                    helper.getView(R.id.my_order_count).setVisibility(View.VISIBLE);
                    if (item.count > 0) {
                        if (item.count < 99) {
                            helper.setText(R.id.my_order_count, String.valueOf(item.count));
                        } else {
                            helper.setText(R.id.my_order_count, String.valueOf("99+"));
                        }
                    } else {
                        helper.getView(R.id.my_order_count).setVisibility(View.GONE);
                    }
                } else {
                    helper.getView(R.id.my_order_count).setVisibility(View.GONE);
                }
                break;
            case MultipleItem.TYPE_BALANCE:
                helper.setText(R.id.my_balance_text, item.mString1);
                helper.addOnClickListener(R.id.my_balance_btn);
                break;
            case MultipleItem.TYPE_TOOLS_HEADER:
                //helper.setText(R.id.tv_item_name, item.mString1);
                break;
            case MultipleItem.TYPE_TOOLS:
                helper.setImageDrawable(R.id.my_tools_image, ContextCompat.getDrawable(mContext, R.drawable.ic_launcher));
                helper.setText(R.id.my_tools_text, item.mString1);
                if (item.isShow) {
                    helper.getView(R.id.my_tools_count).setVisibility(View.VISIBLE);
                    if (item.count > 0) {
                        if (item.count < 99) {
                            helper.setText(R.id.my_tools_count, String.valueOf(item.count));
                        } else {
                            helper.setText(R.id.my_tools_count, String.valueOf("99+"));
                        }
                    } else {
                        helper.getView(R.id.my_tools_count).setVisibility(View.GONE);
                    }
                } else {
                    helper.getView(R.id.my_tools_count).setVisibility(View.GONE);
                }
                break;
        }
    }


The layout of item need not be posted, just the general layout.

The corners (badges) are written directly in ImageView instead of BadgeView.

Demo is drawn from the project, it seems that there is nothing to pay attention to. Forget it.


Demo: https://github.com/yechaoa/MultipleItemPage

Posted by Aliz on Fri, 17 May 2019 04:29:34 -0700