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.