效果图:
先谈实现,再考虑优化,go –>
思路:左边一个listview,右边是一个填充页面的容器,之前考虑用fragment的replace方式管理fragment的添加,后来采用了viewpager管理fragment,使用fragmentpageradapter适配器,因为一级分类会过多造成内存溢出。右侧直接一个recyclerview来承载二级三级分类,使用section可以构造二级分类的条目。
优化也就是代码的重构再重构,控件的性能发挥到极致,用户体验的优化,如加载时的自定义progressbar,重复逻辑的抽取再抽取
代码可直接使用:)
fragment_category.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">
<include layout="@layout/toolbar_category"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ListView
android:id="@+id/listview"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:background="@color/white"
android:choiceMode="singleChoice"
android:scrollbars="none"/>
<!-- <FrameLayout
android:id="@+id/fragment_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3.0"
android:background="@color/white"/>-->
<com.zt.view.customview.MainViewPager
android:id="@+id/fragment_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3.0"
android:background="@color/white"/>
</LinearLayout>
</LinearLayout>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
item_category_left
<?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="wrap_content"
android:orientation="horizontal">
<ImageView
android:visibility="gone"
android:id="@+id/iv_tag"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="@drawable/tag"/>
<TextView
android:background="#f5f5f5"
android:layout_gravity="center"
android:id="@+id/tv_category_first"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingBottom="15dp"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:paddingTop="15dp"
android:textColor="#000000"
android:textSize="14sp">
</TextView>
</LinearLayout>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
禁止左右活动的viewpager
MainViewPager.class
package com.zt.view.customview;
import android.annotation.SuppressLint;
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
/**
* Created by haoran on 2017/3/6.
* 主页面 的 ViewPager 用于填充 tab_home_selected category mine 三个页面
* 禁止左右 滑动
*/
public class MainViewPager extends ViewPager {
/**是否禁止左右滑动,true为禁止,false为不禁止*/
private boolean noScroll = true;
public MainViewPager(Context context) {
this(context,null);
}
public MainViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setNoScroll(boolean noScroll) {
this.noScroll = noScroll;
}
@Override
public void scrollTo(int x, int y) {
super.scrollTo(x, y);
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent arg0) {
if (noScroll)
return false;
else
return super.onTouchEvent(arg0);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent arg0) {
if (noScroll)
return false;
else
return super.onInterceptTouchEvent(arg0);
}
@Override
public void setCurrentItem(int item, boolean smoothScroll) {
super.setCurrentItem(item, smoothScroll);
}
@Override
public void setCurrentItem(int item) {
super.setCurrentItem(item);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
分类页面的实现
CategoryFragment.class
package com.zt.view.fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.ListView;
import com.zt.R;
import com.zt.adapter.CategoryLeftAdapter;
import com.zt.contract.CategoryFragmentMvpView;
import com.zt.model.net.bean.FirstCategory;
import com.zt.presenter.CategoryFragmentPresenter;
import com.zt.view.customview.MainViewPager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
/**
* 作者:haoran on https://github.com/woaigmz 2017/7/26.
* 邮箱:1549112908@qq.com
* 说明:
*/
public class CategoryFragment extends Fragment implements AdapterView.OnItemClickListener, CategoryFragmentMvpView {
@BindView(R.id.listview)
ListView listview;
@BindView(R.id.fragment_container)
MainViewPager fragmentContainer;
private List<FirstCategory.DataBean> category = new ArrayList<>();
private CategoryLeftAdapter categoryLeftAdapter;
private int mPosition;
private ShopAdapter shopAdapter;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_category, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
new CategoryFragmentPresenter(this).getFirstCategoryItem();
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//点击listView回滚居中
mPosition = position;
int totalHeight = listview.getMeasuredHeight() - 120;
listview.smoothScrollToPositionFromTop(mPosition, totalHeight / 2, 50);
//改变条目选中时候的样式,刷新adapter
categoryLeftAdapter.setPosition(mPosition);
categoryLeftAdapter.notifyDataSetChanged();
fragmentContainer.setCurrentItem(mPosition,false);
}
@Override
public void onGetDataCompleted() {
}
@Override
public void onGetDataError(Throwable e) {
}
@Override
public void onGetDataNext(Object o) {
}
@Override
public void onGetDataNext(List<FirstCategory.DataBean> o) {
category = o;
categoryLeftAdapter = new CategoryLeftAdapter(getContext(), category, mPosition);
listview.setAdapter(categoryLeftAdapter);
listview.setOnItemClickListener(this);
//创建MyFragment对象,默认在第一条
fragmentContainer.setCurrentItem(0);
shopAdapter = new ShopAdapter(getChildFragmentManager());
fragmentContainer.setAdapter(shopAdapter);
}
/**
* 适配fragment
*/
private class ShopAdapter extends FragmentPagerAdapter {
ShopAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int arg0) {
Fragment fragment = new GoodsFragment();
Bundle bundle = new Bundle();
bundle.putString("GoodsFragment", category.get(arg0).id+"");
fragment.setArguments(bundle);
return fragment;
}
@Override
public int getCount() {
return category.size();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
左侧的一级分类适配器
CategoryLeftAdapter.class
package com.zt.adapter;
import android.content.Context;
import android.graphics.Color;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.zt.R;
import com.zt.model.net.bean.FirstCategory;
import java.util.List;
/**
* 作者:haoran on https://github.com/woaigmz 2017/8/7.
* 邮箱:1549112908@qq.com
* 说明:
*/
public class CategoryLeftAdapter extends BaseAdapter {
private Context context;
private List<FirstCategory.DataBean> category;
public void setPosition(int mPosition) {
this.mPosition = mPosition;
}
private int mPosition;
public CategoryLeftAdapter(Context context, List<FirstCategory.DataBean> category, int mPosition) {
this.context = context;
this.category = category;
this.mPosition = mPosition;
}
@Override
public int getCount() {
return category.size() == 0 ? 0 : category.size();
}
@Override
public Object getItem(int position) {
return category.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
convertView = View.inflate(context, R.layout.item_category_left, null);
viewHolder = new ViewHolder();
viewHolder.mTextView = (TextView) convertView.findViewById(R.id.tv_category_first);
viewHolder.mImageView = (ImageView) convertView.findViewById(R.id.iv_tag);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.mTextView.setText(category.get(position).name);
if (mPosition == position) {
viewHolder.mImageView.setVisibility(View.VISIBLE);
viewHolder.mTextView.setBackgroundColor(Color.WHITE);
} else {
viewHolder.mImageView.setVisibility(View.GONE);
viewHolder.mTextView.setBackgroundColor(Color.parseColor("#f5f5f5"));
}
return convertView;
}
private final class ViewHolder {
TextView mTextView;
ImageView mImageView;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
显示二级三级分类的内容
GoodsFragment.class
package com.zt.view.fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.zt.R;
import com.zt.adapter.BooKGridLayoutAdapter;
import com.zt.adapter.SectionedGridRecyclerViewAdapter;
import com.zt.contract.GoodFragmentMvpView;
import com.zt.model.net.bean.Book;
import com.zt.presenter.GoodsFragmentPresenter;
import com.zt.view.customview.ScrollGridLayoutManager;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
/**
* 作者:haoran on https://github.com/woaigmz 2017/8/7.
* 邮箱:1549112908@qq.com
* 说明://根据 Bundle 对象 绑定的 tag 显示二级三级分类的内容
*/
public class GoodsFragment extends Fragment implements GoodFragmentMvpView {
public final String TAG = "GoodsFragment";
@BindView(R.id.rv_goods)
RecyclerView rvGoods;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.goodsfragment, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
String tag = getArguments().getString(TAG);
rvGoods.setLayoutManager(new ScrollGridLayoutManager(getContext(), 3, GridLayoutManager.VERTICAL, false) {
@Override
public boolean canScrollVertically() {
return true;
}
});
new GoodsFragmentPresenter(this).getSecondAndThirdCategory(tag);
}
@Override
public void onDestroyView() {
super.onDestroyView();
}
@Override
public void onGetDataCompleted() {
}
@Override
public void onGetDataError(Throwable e) {
}
@Override
public void onGetDataNext(Object o) {
}
@Override
public void onGetDataNext(List<Book> books, SectionedGridRecyclerViewAdapter.Section[] sections) {
BooKGridLayoutAdapter booKGridLayoutAdapter = new BooKGridLayoutAdapter(getContext(), books);
SectionedGridRecyclerViewAdapter sectionedAdapter = new SectionedGridRecyclerViewAdapter(getContext(), R.layout.layout_header_view, R.id.tv_header, rvGoods, booKGridLayoutAdapter);
sectionedAdapter.setSections(sections);
rvGoods.setAdapter(sectionedAdapter);
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
为了使右侧的recyclerview中的条目有分类,构建一个头部
SectionedGridRecyclerViewAdapter.class
package com.zt.adapter;
import android.content.Context;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.Arrays;
import java.util.Comparator;
/**
* Created by haoran on 2017/4/11.
*/
public class SectionedGridRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context mContext;
private static final int SECTION_TYPE = 0;
private boolean mValid = true;
private int mSectionResourceId;
private int mTextResourceId;
private LayoutInflater mLayoutInflater;
private RecyclerView.Adapter mBaseAdapter;
private SparseArray<Section> mSections = new SparseArray<Section>();
private RecyclerView mRecyclerView;
public SectionedGridRecyclerViewAdapter(Context context, int sectionResourceId, int textResourceId,RecyclerView recyclerView,
RecyclerView.Adapter baseAdapter) {
mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mSectionResourceId = sectionResourceId;
mTextResourceId = textResourceId;
mBaseAdapter = baseAdapter;
mContext = context;
mRecyclerView = recyclerView;
mBaseAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
mValid = mBaseAdapter.getItemCount()>0;
notifyDataSetChanged();
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount) {
mValid = mBaseAdapter.getItemCount()>0;
notifyItemRangeChanged(positionStart, itemCount);
}
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
mValid = mBaseAdapter.getItemCount()>0;
notifyItemRangeInserted(positionStart, itemCount);
}
@Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
mValid = mBaseAdapter.getItemCount()>0;
notifyItemRangeRemoved(positionStart, itemCount);
}
});
final GridLayoutManager layoutManager = (GridLayoutManager)(mRecyclerView.getLayoutManager());
layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return (isSectionHeaderPosition(position))? layoutManager.getSpanCount() : 1 ;
}
});
}
public static class SectionViewHolder extends RecyclerView.ViewHolder {
public TextView title;
public SectionViewHolder(View view, int mTextResourceid) {
super(view);
title = (TextView) view.findViewById(mTextResourceid);
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int typeView) {
if (typeView == SECTION_TYPE) {
final View view = LayoutInflater.from(mContext).inflate(mSectionResourceId, parent, false);
return new SectionViewHolder(view,mTextResourceId);
}else{
return mBaseAdapter.onCreateViewHolder(parent, typeView -1);
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder sectionViewHolder, int position) {
if (isSectionHeaderPosition(position)) {
((SectionViewHolder)sectionViewHolder).title.setText(mSections.get(position).title);
}else{
mBaseAdapter.onBindViewHolder(sectionViewHolder,sectionedPositionToPosition(position));
}
}
@Override
public int getItemViewType(int position) {
return isSectionHeaderPosition(position)
? SECTION_TYPE
: mBaseAdapter.getItemViewType(sectionedPositionToPosition(position)) +1 ;
}
public static class Section {
int firstPosition;
int sectionedPosition;
CharSequence title;
public Section(int firstPosition, CharSequence title) {
this.firstPosition = firstPosition;
this.title = title;
}
public CharSequence getTitle() {
return title;
}
}
public void setSections(Section[] sections) {
mSections.clear();
Arrays.sort(sections, new Comparator<Section>() {
@Override
public int compare(Section o, Section o1) {
return (o.firstPosition == o1.firstPosition)
? 0
: ((o.firstPosition < o1.firstPosition) ? -1 : 1);
}
});
int offset = 0; // offset positions for the headers we're adding
for (Section section : sections) {
section.sectionedPosition = section.firstPosition + offset;
mSections.append(section.sectionedPosition, section);
++offset;
}
notifyDataSetChanged();
}
public int positionToSectionedPosition(int position) {
int offset = 0;
for (int i = 0; i < mSections.size(); i++) {
if (mSections.valueAt(i).firstPosition > position) {
break;
}
++offset;
}
return position + offset;
}
public int sectionedPositionToPosition(int sectionedPosition) {
if (isSectionHeaderPosition(sectionedPosition)) {
return RecyclerView.NO_POSITION;
}
int offset = 0;
for (int i = 0; i < mSections.size(); i++) {
if (mSections.valueAt(i).sectionedPosition > sectionedPosition) {
break;
}
--offset;
}
return sectionedPosition + offset;
}
public boolean isSectionHeaderPosition(int position) {
return mSections.get(position) != null;
}
@Override
public long getItemId(int position) {
return isSectionHeaderPosition(position)
? Integer.MAX_VALUE - mSections.indexOfKey(position)
: mBaseAdapter.getItemId(sectionedPositionToPosition(position));
}
@Override
public int getItemCount() {
return (mValid ? mBaseAdapter.getItemCount() + mSections.size() : 0);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_37389474/article/details/77573614