recyclerView 實現複雜的item佈局(如淘寶、京東、商城類首頁)
阿新 • • 發佈:2019-02-03
前言
現在各種電商如火如荼,首頁頁面設計也頗有色彩。
之前專案也是一個電商類購物app,主頁設計了好幾套樣式。
其中一個樣式如下圖相似涉及到: 輪播廣告圖banner
、viewPager的輪播
、沉浸式狀態列
、
recyclerView的item的複雜分割線
、以及自定義的主頁頭條ViewFlipper使用
、glide圖片載入
、其他的瑣碎知識點也略有涉及到。
看下Gif效果圖:
再下引用的第三方控制元件:
//banner
implementation 'com.youth.banner:banner:1.4.10'
//RecyclerView
implementation 'com.android.support:recyclerview-v7:27.1.1'
//RecyclerView Adapter
implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.40'
//圖片載入
implementation 'com.github.bumptech.glide:glide:3.7.0'
//沉浸式
implementation 'com.jaeger.statusbarutil:library:1.5.1'
//retrofit2 轉化器 gson
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
HomeFragment基本程式碼
這裡主要說一下:recyclerView的item的複雜分割線
根據GridLayoutManager
的getSpanSize()
方法可以動態的設定item跨列數;
mRecyclerView.setLayoutManager(new GridLayoutManager(getContext(), 6));
return 6
表示獨佔一個item 比如一張圖片佔滿一行return 3
3是6的多少?2分之1啊,那就是佔一行的一半 也就是說 如果放圖片 一行可以最大放2張!!!return 2
2是6的多少?3分之1啊,那就是佔一行的3分之1 也就是說 如果放圖片 一行可以最大放3張!!!
例如:
根據getItemViewType返回的itemtype,第一個position顯示為輪播圖,
所以返回的是gridManager.getSpanCount(); 即:return 6
如果是2張圖佔滿一行,那麼1張圖就是佔整行的二分之一,既6/2=3, return 3
即可。
public class HomeFragment extends BaseFragment {
private LinearLayout mToolbar;
private RecyclerView mRecyclerView;
private List<TestBean> data;
private int height;
@Override
public int getLayoutId() {
return R.layout.app_fragment_home;
}
@Override
public void initView(View mView) {
mToolbar = mView.findViewById(R.id.toolbar);
mRecyclerView = mView.findViewById(R.id.app_home_list);
}
/**
* 懶載入方法
*/
@Override
public void lazyLoad() {
GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), 6);
mRecyclerView.setLayoutManager(gridLayoutManager);
String jsonData = new String(getAssertsFile(getContext(), "content.json"));
data = new Gson().fromJson(jsonData, new TypeToken<List<TestBean>>() {
}.getType());
TestHomeAdapter adapter = new TestHomeAdapter();
//這裡就要設定分割線了
adapter.setSpanSizeLookup(new BaseQuickAdapter.SpanSizeLookup() {
@Override
public int getSpanSize(GridLayoutManager gridLayoutManager, int position) {
int type = data.get(position).getType();
if (type == 1 || type == 3 || type == 2 || type == 5 || type == 6) {
return 6;
} else if (type == 4) {
return 2;
} else if (type == 7) {
return 3;
}
return 0;
}
});
mRecyclerView.setAdapter(adapter);
adapter.setHeaderView(getHeaderView(mRecyclerView));
adapter.setNewData(data);
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
private int totalDy = 0;
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
totalDy += dy;
if (totalDy <= height) {
float alpha = (float) totalDy / height;
mToolbar.setBackgroundColor(ColorUtils.blendARGB(Color.TRANSPARENT
, ContextCompat.getColor(getContext(), R.color.white), alpha));
} else {
mToolbar.setBackgroundColor(ColorUtils.blendARGB(Color.TRANSPARENT
, ContextCompat.getColor(getContext(), R.color.white), 1));
}
}
});
}
/**
* 輪播圖banner的資料設定
*/
private View getHeaderView(RecyclerView v) {
List<String> bannerImg = new ArrayList<>();
bannerImg.add("圖片地址1.jpg");
bannerImg.add("圖片地址2.jpg");
bannerImg.add("圖片地址3.jpg");
bannerImg.add("http://58.87.71.247:8080/TestFile/banner.png");
View convertView = LayoutInflater
.from(getContext())
.inflate(R.layout.app_include_home_header, (ViewGroup) v.getParent(), false);
Banner mBanner = convertView.findViewById(R.id.app_home_header_banner);
mBanner.setImages(bannerImg)
.setImageLoader(new GlideImageLoader())
.setDelayTime(3000)
.start();
MarqueeView marqueeView = convertView.findViewById(R.id.app_home_header_problem);
//頭條資料ViewFlipper
List<String> problems = new ArrayList<>();
problems.add("如何獲取更多個人積分");
problems.add("下單時服務費率規則");
problems.add("大額預定商品詳細交易流程");
marqueeView.startWithList(problems);
ViewGroup.LayoutParams bannerParams = mBanner.getLayoutParams();
int resourceId = getContext().getResources().getIdentifier("status_bar_height",
"dimen","android");
int statusBarHeight = getContext().getResources().getDimensionPixelSize(resourceId);
height = bannerParams.height - statusBarHeight - 104;
return convertView;
}
//模擬後臺請求資料 存放在AssertsFile資料夾裡
public static byte[] getAssertsFile(Context context, String fileName) {
InputStream inputStream = null;
//讀取資源
AssetManager assetManager = context.getAssets();
try {
inputStream = assetManager.open(fileName);
if (inputStream == null) {
return null;
}
BufferedInputStream bis = null;
int length;
try {
bis = new BufferedInputStream(inputStream);
length = bis.available();
byte[] data = new byte[length];
bis.read(data);
return data;
} catch (IOException e) {
} finally {
if (bis != null) {
try {
bis.close();
} catch (Exception e) {
}
}
}
return null;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
基類Fragment
public abstract class BaseFragment extends Fragment {
View mView;
boolean isLoad = false;
boolean isInit = false;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (mView == null)
mView = inflater.inflate(getLayoutId(), container, false);
isInit = true;
initView(mView);
isCanLoadData();
return mView;
}
public abstract void initView(View mView);
/**
* 檢視是否已經對使用者可見,系統的方法
*/
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
isCanLoadData();
}
/**
* 懶載入
*/
private void isCanLoadData() {
if (!isInit) {
return;
}
if (getUserVisibleHint() && !isLoad) {
lazyLoad();
isLoad = true;
} else {
if (isLoad) {
stopLoad();
}
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
isInit = false;
}
/**
* 第一次載入的處理 此處可以留給載入網路去處理
*/
public void lazyLoad() {
}
/**
* 頁面停止載入的處理
*/
public void stopLoad() {
}
public abstract int getLayoutId();
}
核心adapter
public class TestHomeAdapter extends MultipleItemRvAdapter<TestBean, BaseViewHolder> {
//通欄商品大圖片
public static final int TYPE_IMG = 100;
//通欄圖文
public static final int TYPE_TEXT_AND_IMG = 200;
//通欄文字
public static final int TYPE_TEXT = 300;
//三列
public static final int TYPE_THREE_COLUMN = 400;
//通欄水平拖動
public static final int TYPE_HORIZONTAL_SCROLL = 500;
//通欄窄圖片
public static final int TYPE_NARROW_IMG = 600;
//兩列
public static final int TYPE_TWO_COLUMN = 700;
public TestHomeAdapter() {
super(null);
finishInitialize();
}
@Override
protected int getViewType(TestBean testBean) {
int type = testBean.getType();
if (type == 1) {
return TYPE_IMG;
} else if (type == 2) {
return TYPE_TEXT_AND_IMG;
} else if (type == 3) {
return TYPE_TEXT;
} else if (type == 4) {
return TYPE_THREE_COLUMN;
} else if (type == 5) {
return TYPE_HORIZONTAL_SCROLL;
} else if (type == 6) {
return TYPE_NARROW_IMG;
} else if (type == 7) {
return TYPE_TWO_COLUMN;
}
return 0;
}
@Override
public void registerItemProvider() {
//通欄商品大圖片
mProviderDelegate.registerProvider(new ImgItemProvider());
//通欄圖文
mProviderDelegate.registerProvider(new ImgAndTextItemProvider());
//通欄文字
mProviderDelegate.registerProvider(new TextItemProvider());
//三列圖文
mProviderDelegate.registerProvider(new ThreeColumnItemProvider());
//通欄橫向滑動
mProviderDelegate.registerProvider(new ScrollItemProvider());
//通欄窄圖片
mProviderDelegate.registerProvider(new NarrowImgItemProvider());
//兩列圖文
mProviderDelegate.registerProvider(new TwoColumnItemProvider());
}
}
demo地址:
與君共勉
我要一步一步往上爬
在最高點乘著葉片往前飛
任風吹乾流過的淚和汗
我要一步一步往上爬
等待陽光靜靜看著它的臉
小小的天有大大的夢想
我有屬於我的天
任風吹乾流過的淚和汗
總有一天我有屬於我的天