首先内容页面使用RecyclerView控件。
RecyclerView是一个强大的滑动组件。
RecyclerView的四大主要组成是:
* Layout Manager:Item的布局。
* Adapter:为Item提供数据。
* Item Decoration:Item之间的Divider。
* Item Animator:添加、删除Item动画。
RecyclerView提供了三种布局
1)、LinerLayoutManager
以垂直或者水平列表方式展示Item
2)、GridLayoutManager
以网格方式展示Item
3)、StaggeredGridLayoutManager
以瀑布流方式展示Item
4)、自定义
继承实现自己的 LayoutManager,并重写相应的方法
游戏社区App内容页面使用GridLayoutManager网格布局。
GridLayoutManager构造函数和参数含义
GridLayoutManager(Context context, int spanCount, int orientation,boolean reverseLayout)
spanCount:每行item的个数
orientation:方向,OrientationHelper.HORIZONTA 或者 OrientationHelper.VERTICAL
reverseLayout:是否逆向,true:布局逆向展示,false:布局正向显示
功能就是为RecyclerView提供数据。
这里可以使用万能适配器–BaseRecyclerViewAdapterHelper
首先在build.gradle中添加依赖
api 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.16'
并且在工程的build.gradle中添加
allprojects {
repositories {
...
maven { url "https://jitpack.io" }
google()
jcenter()
...
}}
public class MultipleItemEntity implements MultiItemEntity {
private final ReferenceQueue<LinkedHashMap<Object, Object>> ITEM_QUEUE=new ReferenceQueue<>();
private final LinkedHashMap<Object, Object> MUITIPLE_FIELDS=new LinkedHashMap<>();
private final SoftReference<LinkedHashMap<Object, Object>> FIELDS_REFERENCE=
new SoftReference<>(MUITIPLE_FIELDS,ITEM_QUEUE);
public MultipleItemEntity(LinkedHashMap<Object, Object> fields){
FIELDS_REFERENCE.get().putAll(fields);
}
public static MultipleItemEntityBuilder builder(){
return new MultipleItemEntityBuilder();
}
@Override
public int getItemType() {
return (int) FIELDS_REFERENCE.get().get(MultipleFields.ITEM_TYPE);
}
@SuppressWarnings("unchecked")
public final <T> T getField(Object key){
return (T) FIELDS_REFERENCE.get().get(key);
}
public final LinkedHashMap<?,?> getFields(){
return FIELDS_REFERENCE.get();
}
public final MultiItemEntity setField(Object key, Object value){
FIELDS_REFERENCE.get().put(key, value);
return this;
}
}
public class MultipleRecyclerAdapter extends BaseMultiItemQuickAdapter<MultipleItemEntity,MultIpleViewHolder>
implements BaseQuickAdapter.SpanSizeLookup,
OnItemClickListener {
private boolean mIsInitBanner=false;//确保初始化一次banner,防止重复item加载
private static int bannerPosition=0;//banner轮播图的序号
protected MultipleRecyclerAdapter(List<MultipleItemEntity> data) {
super(data);
init();
}
public static MultipleRecyclerAdapter create(List<MultipleItemEntity> data){
return new MultipleRecyclerAdapter(data);
}
public static MultipleRecyclerAdapter create(DataConverter converter){
return new MultipleRecyclerAdapter(converter.convert());
}
private void init(){
//对不同的ItemType设置对应的布局
addItemType(ItemType.TITLE, R.layout.item_multiple_title);
addItemType(ItemType.BUTTON, R.layout.item_multiple_button);
addItemType(ItemType.BANNER, R.layout.item_multiple_banner);
.......(省略)
//设置宽度的监听
setSpanSizeLookup(this);
//使用动画
openLoadAnimation();
//不多次执行动画
isFirstOnly(false);
}
@Override
protected MultIpleViewHolder createBaseViewHolder(View view) {
return MultIpleViewHolder.create(view);
}
@Override
protected void convert(MultIpleViewHolder holder, MultipleItemEntity entity) {
final String title;
final String synopsis;
final String text;
final String imageUrl;
final ArrayList<String> bannerImages;
switch (holder.getItemViewType()){
case ItemType.TITLE:
title=entity.getField(MultipleFields.TITLE);
synopsis=" "+entity.getField(MultipleFields.SYNOPSIS);
holder.setText(R.id.text_title,title);
holder.setText(R.id.text_synopsis,synopsis);
break;
case ItemType.BUTTON:
text=entity.getField(MultipleFields.TEXT);
imageUrl=entity.getField(MultipleFields.IMAGE_URL);
Glide.with(mContext)
.load(imageUrl)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.dontAnimate()
.centerCrop()
.into((ImageView) holder.getView(R.id.img_multiple));
holder.setText(R.id.tv_multiple,text);
break;
case ItemType.BANNER:
if(!mIsInitBanner){
bannerImages=entity.getField(MultipleFields.BANNERS);
final ConvenientBanner<String> convenientBanner=holder.getView(R.id.banner_recycler_item);
BannerCreator.setDefault(convenientBanner, bannerImages, new com.bigkoo.convenientbanner.listener.OnItemClickListener() {
@Override
public void onItemClick(int position) {
bannerPosition=position;
}
});
mIsInitBanner=true;
}
break;
default:
break;
}
}
public static int getBannerPosition(){
return bannerPosition;
}
@Override
public int getSpanSize(GridLayoutManager gridLayoutManager, int position) {
return getData().get(position).getField(MultipleFields.SPAN_SIZE);
}
@Override
public void onItemClick(int position) {
}
}
mAdapter=MultipleRecyclerAdapter.create(data);
可以为item之间添加分割线。
任何分割线样式都需要自己实现
继承RecyclerView.ItemDecoration抽象类,并实现三个方法:
onDraw(Canvas c, RecyclerView parent, State state)
用于绘制间隔样式
onDrawOver(Canvas c, RecyclerView parent, State state)
用于绘制间隔样式
onDraw()和onDrawOver() 都是用于绘制间隔样式,只需要复写其中一个方法即可。
getItemOffsets(Rect outRect, View view, RecyclerView parent, State state)
设置item的偏移量,偏移的部分用于填充间隔样式
也可以使用RecyclerView的分割线RecyclerView_Divider
RecyclerView能够通过mRecyclerView.setItemAnimator(ItemAnimator animator)设置添加、删除、移动、改变的动画效果。
也可以直接使用默认动画DefaultItemAnimator,一般没特殊需求,使用默认动画即可。
Item中图片的加载,使用Glide图片加载库。
只需引入依赖
//Glide
api 'com.github.bumptech.glide:glide:3.7.0'
api 'com.github.bumptech.glide:okhttp3-integration:1.4.0@aar'
在需要加载图片的地方调用
String url = "http://xxx.jpg";
ImageView imageView = (ImageView) findViewById(R.id.imageView);
Glide.with(context)
.load(url)
.into(imageView);
使用Transformations可以对图片进行处理,包括圆角,灰阶等等。
这里需要对Item中的图片进行圆角的处理
示例代码:
public class RoundTransformation extends BitmapTransformation {
private float radius = 0f;
public RoundTransformation(Context context) {
this(context, 4);
}
public RoundTransformation(Context context, int px) {
super(context);
this.radius = px;
}
@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
LocalLogUtils.d("roundCrop",true);
return roundCrop(pool, toTransform);
}
private Bitmap roundCrop(BitmapPool pool, Bitmap source) {
LocalLogUtils.d("roundCrop",true);
if (source == null)
return null;
LocalLogUtils.d("result",true);
LocalLogUtils.d("source.getWidth()="+source.getWidth()+" ,source.getHeight()="+source.getHeight(),true);
Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
if (result == null) {
result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
paint.setAntiAlias(true);
RectF rectF = new RectF(0f, 0f, source.getWidth(), source.getHeight());
canvas.drawRoundRect(rectF, radius, radius, paint);
return result;
}
@Override
public String getId() {
return getClass().getName() + Math.round(radius);
}
}
使用时调用 .transform() 方法,将自定义的 Transformation 的对象作为参数传递进去就可以了。
示例代码:
String url = "http://xxx.jpg";
ImageView imageView = (ImageView) findViewById(R.id.imageView);
Glide.with(context)
.load(url)
.transform(new RoundTransformation(context , 20))
.into(imageView);
同时对图片进行圆角等处理,也可以使用第三方库Glide-transformations进行处理。
轮播图使用ConvenientBanner图片轮播控件。ConvenientBanner支持无限循环,支持设置自动翻页和时间。
ConvenientBanner的使用
引入依赖
api 'com.bigkoo:convenientbanner:2.0.5'
api 'com.ToxicBakery.viewpager.transforms:view-pager-transforms:1.2.32@aar'
布局
<com.bigkoo.convenientbanner.ConvenientBanner
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/banner_recycler_item"
android:layout_width="match_parent"
android:layout_height="200dp"
/>
使用
convenientBanner.setPages(new HolderCreator(),banner)
.setPageIndicator(new int[]{R.drawable.dot_normal,R.drawable.dot_focus}) //设置两个点的图片作为翻页指示器
.setPageIndicatorAlign(ConvenientBanner.PageIndicatorAlign.CENTER_HORIZONTAL) //设置指示器的方向
.setOnItemClickListener(clickListener) //监听点击事件
.setPageTransformer(new DefaultTransformer()) //设置翻页动画
.startTurning(3000);//设置翻页时间间隔
图片加载也是使用Glide,并且对图片进行圆角处理
public class ImageHolder implements Holder<String> {
private AppCompatImageView mImageView=null;
@Override
public View createView(Context context) {
mImageView=new AppCompatImageView(context);
return mImageView;
}
@Override
public void UpdateUI(Context context, int position, String data) {
Glide.with(context)
.load(data)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.dontAnimate()
.fitCenter()
.transform(new RoundTransformation(context,10))
.into(mImageView);
}
}
1、大概流程
从后台获取数据–>对数据进行整理–>填充进页面
2、从后台获取数据
后台数据要分页获取,每次获取一页的数据,并把页数存储起来。当上拉加载时 再获取下一页的数据。
上一篇:游戏社区App (四):底部导航栏
下一篇:游戏社区App (六):文章编辑与上传