之前已经详细讲述了主页面的编写,有疑问的小伙伴可以点此处https://www.jianshu.com/p/e9f08581b514
Mall商城页面编写大致差不多,有些相同的地方就不在赘述了,下面看代码
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_fragment_mall_context"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/White"
android:clipToPadding="true"
android:descendantFocusability="blocksDescendants"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:requiresFadingEdge="none"
android:scrollbars="none" />
</android.support.v4.widget.SwipeRefreshLayout>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar_mall"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorYellow"
app:layout_behavior="lf.com.android.blackfishdemo.util.MallBarAlphaBehavior">
<RelativeLayout
android:id="@+id/rl_mall_header"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="20dp">
<ImageView
android:id="@+id/iv_mall_heard_menu"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_centerVertical="true"
android:layout_marginTop="10dp"
android:scaleType="fitXY"
android:src="@drawable/stages_icon_classify_white" />
<RelativeLayout
android:id="@+id/rl_mall_head_layout"
android:layout_width="match_parent"
android:layout_height="25dp"
android:layout_centerVertical="true"
android:layout_marginEnd="40dp"
android:layout_marginStart="10dp"
android:layout_marginTop="12.5dp"
android:layout_toEndOf="@+id/iv_mall_heard_menu"
android:background="@drawable/shape_search_view">
<ImageView
android:id="@+id/iv_search_logo"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_centerVertical="true"
android:layout_marginStart="10dp"
android:src="@drawable/stages_icon_search" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="10dp"
android:layout_toRightOf="@id/iv_search_logo"
android:background="@color/color_rv_bg"
android:hint="HuaWei P10"
android:textSize="13sp" />
</RelativeLayout>
<ImageView
android:id="@+id/iv_mall_header_msg"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="10dp"
android:layout_marginTop="12.5dp"
android:src="@drawable/icon_home_header_msg_white" />
</RelativeLayout>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CoordinatorLayout>
布局是由Toolbar和RecyclerView组成的。和之前的并没有什么差异,
也是需要配置adapter,只是布局不同罢了,其他的都是大同小异
这里需要注意的是behavior,什么是behavior?
Behavior就是执行你定制的动作。Interaction behavior plugin for child views of CoordinatorLayout. 作用于CoordinatorLayout的子View的交互行为插件。一个Behavior 实现了用户的一个或者多个交互行为,它们可能包括拖拽、滑动、快滑或者其他一些手势。在讲Behavior之前必须先理解两个概念:Child和Dependency,什么意思呢?Child当然是子View的意思了,是谁的子View呢,当然是CoordinatorLayout的子View;其实Child是指要执行动作的CoordinatorLayout的子View。而Dependency是指Child依赖的View。如过Dependency这个View发生了变化,那么Child这个View就要相应发生变化。发生变化是具体发生什么变化呢?这里就要引入Behavior,Child发生变化的具体执行的代码都是放在Behavior这个类里面。
Behavior 是一个顶层抽象类,其他的一些具体行为的Behavior 都是继承自这个类。它提供了几个重要的方法:
- layoutDependsOn
/**
* 表示是否给应用了Behavior 的View 指定一个依赖的布局,通常,当依赖的View 布局发生变化时
* 不管被被依赖View 的顺序怎样,被依赖的View也会重新布局
* @param parent
* @param child 绑定behavior 的View
* @param dependency 依赖的view
* @return 如果child 是依赖的指定的View 返回true,否则返回false
*/
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
return super.layoutDependsOn(parent, child, dependency);
}
- onDependentViewChanged
/**
* 当被依赖的View 状态(如:位置、大小)发生变化时,这个方法被调用
* @param parent
* @param child
* @param dependency
* @return
*/
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
return super.onDependentViewChanged(parent, child, dependency);
}
- onStartNestedScrol
/**
* 当coordinatorLayout 的子View试图开始嵌套滑动的时候被调用。当返回值为true的时候表明
* coordinatorLayout 充当nested scroll parent 处理这次滑动,需要注意的是只有当返回值为true
* 的时候,Behavior 才能收到后面的一些nested scroll 事件回调(如:onNestedPreScroll、onNestedScroll等)
* 这个方法有个重要的参数nestedScrollAxes,表明处理的滑动的方向。
*
* @param coordinatorLayout 和Behavior 绑定的View的父CoordinatorLayout
* @param child 和Behavior 绑定的View
* @param directTargetChild
* @param target
* @param nestedScrollAxes 嵌套滑动 应用的滑动方向,看 {@link ViewCompat#SCROLL_AXIS_HORIZONTAL},
* {@link ViewCompat#SCROLL_AXIS_VERTICAL}
* @return
*/
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
return super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
}
- onNestedPreScroll
/**
* 嵌套滚动发生之前被调用
* 在nested scroll child 消费掉自己的滚动距离之前,嵌套滚动每次被nested scroll child
* 更新都会调用onNestedPreScroll。注意有个重要的参数consumed,可以修改这个数组表示你消费
* 了多少距离。假设用户滑动了100px,child 做了90px 的位移,你需要把 consumed[1]的值改成90,
* 这样coordinatorLayout就能知道只处理剩下的10px的滚动。
* @param coordinatorLayout
* @param child
* @param target
* @param dx 用户水平方向的滚动距离
* @param dy 用户竖直方向的滚动距离
* @param consumed
*/
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) {
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
}
- onNestedScroll
/**
* 进行嵌套滚动时被调用
* @param coordinatorLayout
* @param child
* @param target
* @param dxConsumed target 已经消费的x方向的距离
* @param dyConsumed target 已经消费的y方向的距离
* @param dxUnconsumed x 方向剩下的滚动距离
* @param dyUnconsumed y 方向剩下的滚动距离
*/
@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
}
- onStopNestedScroll
/**
* 嵌套滚动结束时被调用,这是一个清除滚动状态等的好时机。
* @param coordinatorLayout
* @param child
* @param target
*/
@Override
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target) {
super.onStopNestedScroll(coordinatorLayout, child, target);
}
- onNestedScrollAccepted
/**
* onStartNestedScroll返回true才会触发这个方法,接受滚动处理后回调,可以在这个
* 方法里做一些准备工作,如一些状态的重置等。
* @param coordinatorLayout
* @param child
* @param directTargetChild
* @param target
* @param nestedScrollAxes
*/
@Override
public void onNestedScrollAccepted(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
super.onNestedScrollAccepted(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
}
- onNestedPreFling
/**
* 用户松开手指并且会发生惯性动作之前调用,参数提供了速度信息,可以根据这些速度信息
* 决定最终状态,比如滚动Header,是让Header处于展开状态还是折叠状态。返回true 表
* 示消费了fling.
*
* @param coordinatorLayout
* @param child
* @param target
* @param velocityX x 方向的速度
* @param velocityY y 方向的速度
* @return
*/
@Override
public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY) {
return super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY);
}
- onLayoutChild
//可以重写这个方法对子View 进行重新布局
@Override
public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) {
return super.onLayoutChild(parent, child, layoutDirection);
}
ok,大家对behavior有了一定的认识后,我们来去看下自定义behavior怎么去编写吧
public class MallBarAlphaBehavior extends CoordinatorLayout.Behavior<Toolbar> {
private int offset = 0;
private int startOffset = 0;
private int endOffset = 0;
private Context mContext;
public MallBarAlphaBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
}
@Override
public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull Toolbar child, @NonNull View directTargetChild, @NonNull View target, int axes, int type) {
return true;
}
@Override
public void onNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull Toolbar child, @NonNull View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
startOffset = 0;
endOffset = child.getHeight();//返回子视图的高度
offset += dyConsumed;//叠加在Y轴上消耗的距离
RelativeLayout relativeLayout = (RelativeLayout) child.getChildAt(0);
ImageView imageMenu = (ImageView) relativeLayout.getChildAt(0);//获取指定视图
ImageView imageMsg = (ImageView) relativeLayout.getChildAt(2);//获取指定视图
if (offset <= startOffset) {//如果Y轴上消耗的距离<=0的话,就将子view透明度设置为0
child.getBackground().setAlpha(0);
} else if (offset > startOffset && offset < endOffset) {//如果滑动的距离大于0,并且滑动范围在子view视图里面
imageMsg.setImageDrawable(mContext.getResources().getDrawable(R.drawable.icon_home_header_msg_white));
imageMenu.setImageDrawable(mContext.getResources().getDrawable(R.drawable.stages_icon_classify_white));
float precent = (float) (offset - startOffset) / endOffset;
int alpha = Math.round(precent * 255);
child.getBackground().setAlpha(alpha);
imageMenu.getDrawable().setAlpha(1 - alpha);
imageMsg.getDrawable().setAlpha(1 - alpha);
} else if (offset >= endOffset) {//滑动距离超过了子veiw的范围
child.getBackground().setAlpha(255);
imageMsg.setImageDrawable(mContext.getResources().getDrawable(R.drawable.icon_home_header_msg_black));
imageMenu.setImageDrawable(mContext.getResources().getDrawable(R.drawable.stages_icon_classify_gray));
imageMenu.setVisibility(View.VISIBLE);
imageMenu.setAlpha(1f);
imageMsg.setVisibility(View.VISIBLE);
imageMsg.setAlpha(1f);
}
}
}
可以看到首先我们需要将onStartNestedScroll返回值设置为true,才能让behavior拦截到后续的方法。思路大致是监听onNestedScroll方法,因为,只要控件产生位移,就会调用此方法,首先定义三个变量,
startOffset表示控件未产生滑动的时候位置,endOffset表示子控件在视图中的高度,offset表示累加当前滑动距离。如果当前滑动距离小于等于0时候,我们可以认为控件是静止的,因为这里并不是相对滑动,而是绝对滑动,不存在负值,继而我们判断滑动时候的状态,滑动是否在我们子控件的范围内还是超出了子控件的范围,分别写上不同的逻辑。这样,我们的behavior就写好了,我们在之前的XML文件中已经添加过了,就是这行代码
app:layout_behavior="lf.com.android.blackfishdemo.util.MallBarAlphaBehavior">
下面展示一下效果
注意我们的标题栏,是不是变色了,哈哈。接下来的代码和之前的商城商城页面代码也没有啥区别,首先是轮播图的代码
final SingleLayoutHelper layoutHelper = new SingleLayoutHelper();
GeneralVLayoutAdapter bannerAdapter = new GeneralVLayoutAdapter(mContext, layoutHelper, 1) {
@NonNull
@Override
public MainViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(
mContext).inflate(R.layout.mall_pager_banner_layout, viewGroup, false);
return new MainViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MainViewHolder mainViewHolder, int i) {
super.onBindViewHolder(mainViewHolder, i);
mBanner = mainViewHolder.itemView.findViewById(R.id.rvb_mall_header);
mBannerInfos = mallPagerInfo.getmBannerInfos();
mBanner.setRvBannerData(mBannerInfos);
mBanner.setOnSwitchRvBannerListener(new OnSwitchRvBannerListener() {
@Override
public void switchBanner(int position, SimpleDraweeView draweeView) {
draweeView.setImageURI(mBannerInfos.get(position).getUrl());
}
});
mBanner.setListener(new OnRvBannerClickListener() {
@Override
public void OnClick(int position) {
Intent intent = new Intent(mContext, BaseWebViewActivity.class);
intent.putExtra("loadUrl", "https://github.com/LF1165339017");
startActivity(intent);
getActivity().overridePendingTransition(R.anim.activity_right_in, 0);
}
});
}
};
adapters.add(bannerAdapter);
这里还是一样要重写 onCreateViewHolder和onBindViewHolder方法,先引入布局,然后获取数据源填充进轮播图里面.这里需要注意是我们自定义了一个接口用来设置轮播图片和监听点击事件,轮播图在之前有详细讲解,如果有需要跟深入了解轮播图请点击。Ok,下面开始编写新的代码。
GridLayoutHelper gridLayoutHelper = new GridLayoutHelper(5);
GeneralVLayoutAdapter gridAdapter = new GeneralVLayoutAdapter(mContext, gridLayoutHelper, 10) {
@NonNull
@Override
public MainViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(mContext).inflate(
R.layout.mall_pager_two_line_grid, viewGroup, false);
return new MainViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MainViewHolder mainViewHolder, final int i) {
super.onBindViewHolder(mainViewHolder, i);
mImageGridItem = mainViewHolder.itemView.findViewById(R.id.iv_mall_grid_item);
mTextGridItem = mainViewHolder.itemView.findViewById(R.id.tv_mall_grid_item);
mGridInfos = mallPagerInfo.getmClassifyInfo();
mImageGridItem.setImageURI(mGridInfos.get(i).getImageUrl());
mTextGridItem.setText(mGridInfos.get(i).getTitle());
mImageGridItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onItemClick("ClassifyGridItem" + i);
}
});
}
};
adapters.add(gridAdapter);
这段代码也很简单,这是一个网格布局,我们设定为5列,
GridLayoutHelper gridLayoutHelper = new GridLayoutHelper(5)
然后adapter中添加子view的个数
GeneralVLayoutAdapter gridAdapter = new GeneralVLayoutAdapter(mContext, gridLayoutHelper, 10){}
并重写onCreateViewHolder,onBindViewHolder这两种方法,也没有啥好说的,比较简单,就不在赘述了。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/iv_four_header_image"
android:layout_width="match_parent"
android:layout_height="80dp" />
<lf.com.android.blackfishdemo.view.GridViewForScroll
android:id="@+id/gv_four_goods"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:numColumns="2"
android:paddingStart="5dp"
android:horizontalSpacing="2dp"
android:verticalSpacing="2dp"
android:stretchMode="columnWidth"
android:layout_below="@+id/iv_four_header_image"
/>
</RelativeLayout>
这段XML文件也比较简单,使用的SimpleDrawweeView和自定义的GridViewForScroll,SimpleDraweeView是用来放图片的,那么来看看GridViewForScoll用途。
package lf.com.android.blackfishdemo.view;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.GridView;
public class GridViewForScroll extends GridView {
public GridViewForScroll(Context context) {
super(context);
}
public GridViewForScroll(Context context, AttributeSet attrs) {
super(context, attrs);
}
public GridViewForScroll(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec + 30);
}
}
这里我们继承GridView并重写了三个构造方法,这个没啥好说的。重点时是 onMeasure这个方法,它是自定义View的测量过程,关于自定义view的方法,请点击这里。
这里会重写onMeasure方法是因为在一般情况下使用GridView、listView其实都是高度填充父类窗体(fill_parent、match_parent),那么UI显示正常,不过,当在这个外面嵌套一个垂直方向滚动的布局(ScrollView)之后,特殊情况就出现了。listview的滑动冲突。gridView的显示一行等
大概的意思是能获取到测量的View的高度,然后+30dp,保证控件的上下间距。就不再深究了。
SingleLayoutHelper fourGoodsHelper = new SingleLayoutHelper();
GeneralVLayoutAdapter fourGoodsAdapter = new GeneralVLayoutAdapter(mContext, fourGoodsHelper, 1) {
@NonNull
@Override
public MainViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(mContext).inflate(
R.layout.mall_pager_four_goods_layout, viewGroup, false);
return new MainViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MainViewHolder mainViewHolder, int i) {
super.onBindViewHolder(mainViewHolder, i);
SimpleDraweeView headerImage = mainViewHolder.itemView.findViewById(R.id.iv_four_header_image);
GridViewForScroll gridFourGoods = mainViewHolder.itemView.findViewById(R.id.gv_four_goods);
gridFourGoods.setAdapter(new GridOnlyImageAdapter(mContext, mallPagerInfo.getmGridGoodsInfos()));
headerImage.setImageURI(mallPagerInfo.getSingleImageUrl());
headerImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onItemClick("SingleHeaderImage");
}
});
}
};
adapters.add(fourGoodsAdapter);
GridLayoutHelper gridHotClassifyHelper = new GridLayoutHelper(1);
GeneralVLayoutAdapter hotClassifyAdapter = new GeneralVLayoutAdapter(
mContext, gridHotClassifyHelper, mallPagerInfo.getmMallGoodsInfos().size()) {
@NonNull
@Override
public MainViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(mContext).inflate(
R.layout.mall_pager_hot_classify_grid_layout, viewGroup, false);
return new MainViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MainViewHolder mainViewHolder, final int i) {
super.onBindViewHolder(mainViewHolder, i);
List<MallHotClassifyGridInfo> mallHotClassifyGridInfos = new ArrayList<>();
SimpleDraweeView headerImage = mainViewHolder.itemView.findViewById(R.id.iv_hot_classify_header_image);
GridViewForScroll gridGoods = mainViewHolder.itemView.findViewById(R.id.gv_hot_classify);
List<MallGoodsInfo> mallGoodsInfos = mallPagerInfo.getmMallGoodsInfos();
headerImage.setImageURI(mallGoodsInfos.get(i).getHeadImageUrl());
headerImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onItemClick("HotGoodsHeaderImage" + i);
}
});
int itemSize = mallGoodsInfos.get(i).getmMallGoodsItemInfos().size();
for (int j = 0; j < itemSize; j++) {
MallGoodsItemInfo mallGoodsItemInfo = mallGoodsInfos.get(i).getmMallGoodsItemInfos().get(i);
String goodsImage = mallGoodsItemInfo.getImageUrl();
String goodsDesc = mallGoodsItemInfo.getDesc();
String goodsPeriods = "¥" + mallGoodsItemInfo.getSinglePrice()
+ " x " + mallGoodsItemInfo.getPeriods() + "期";
String goodsPrice = "¥" + mallGoodsItemInfo.getPrice();
mallHotClassifyGridInfos.add(new MallHotClassifyGridInfo(goodsImage, goodsDesc, goodsPeriods, goodsPrice));
}
MallHotClassifyGridAdapter adapter = new MallHotClassifyGridAdapter(mContext, mallHotClassifyGridInfos);
adapter.setmOnViewItemClickListener(onViewItemClickListener);
gridGoods.setAdapter(adapter);
}
};
adapters.add(hotClassifyAdapter);
这一段代码和上面大同小异,也就不再深究了,我们主要来看下面这一段代码
final SingleLayoutHelper recoHelper = new SingleLayoutHelper();
GeneralVLayoutAdapter recoAdapter = new GeneralVLayoutAdapter(mContext, recoHelper, 1) {
@NonNull
@Override
public MainViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(mContext).inflate(R.layout.mall_pager_recommend_goods_list, viewGroup, false);
return new MainViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MainViewHolder mainViewHolder, int i) {
super.onBindViewHolder(mainViewHolder, i);
RecyclerView recyclerView = mainViewHolder.itemView.findViewById(R.id.rv_mall_recommend);
List<RecommendGoodsInfo> recommendGoodsInfos = mallPagerInfo.getmRecommendGoodsInfos();
recyclerView.setLayoutManager(new LinearLayoutManager(mContext));
recyclerView.addItemDecoration(new DividerItemDecoration(mContext, DividerItemDecoration.VERTICAL));
recyclerView.setAdapter(new RecommendGoodsAdapter(mContext, recommendGoodsInfos));
}
};
adapters.add(recoAdapter);
上面的代码格式还是大同小异,我们来看下布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/rl_mall_recommend_title_layout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/White">
<ImageView
android:layout_width="80dp"
android:layout_height="8dp"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_marginStart="70dp"
android:src="@drawable/icon_recommend_title_left" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="为你推荐"
android:textColor="@color/Black"
android:textSize="18sp" />
<ImageView
android:layout_width="80dp"
android:layout_height="8dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="70dp"
android:src="@drawable/icon_recommend_title_right" />
</RelativeLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_mall_recommend"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/rl_mall_recommend_title_layout"
android:layout_marginBottom="30dp"
android:background="@color/White" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_below="@+id/rv_mall_recommend">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:gravity="center_horizontal|bottom"
android:text="---------- 已经到底了 ------------"
android:textColor="@color/Black"
android:textSize="12sp" />
</FrameLayout>
</RelativeLayout>
这里的布局也很简单,一个头部Title+RecyclerView+底部Title,没啥好说的,我们来关注下RecyclerView的adapter布局吧。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="@color/White">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/iv_mall_recommend_goods_image"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerVertical="true"
android:layout_marginStart="25dp" />
<TextView
android:id="@+id/tv_mall_recommend_goods_desc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="30dp"
android:layout_toRightOf="@+id/iv_mall_recommend_goods_image"
android:ellipsize="end"
android:maxLines="2"
android:textColor="@color/Black" />
<TextView
android:id="@+id/tv_mall_recommend_goods_price"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_mall_recommend_goods_desc"
android:layout_marginStart="10dp"
android:layout_marginTop="20dp"
android:layout_toRightOf="@+id/iv_mall_recommend_goods_image"
android:maxLines="1"
android:text="¥27.72x12期 ¥298.00"
android:textColor="@color/Black" />
<TextView
android:id="@+id/tv_mall_recommend_goods_evaluation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/iv_mall_recommend_goods_image"
android:layout_centerHorizontal="true"
android:background="@drawable/shape_evaluation_text"
android:paddingBottom="2dp"
android:paddingEnd="10dp"
android:paddingStart="10dp"
android:paddingTop="2dp"
android:text="好评率:99%"
android:textColor="@color/Black"
android:textSize="12sp" />
</RelativeLayout>
这里的布局是一个SimpleView配上简介效果,类似于商品简介
OK,大致的界面就编写完成了,贴上adapter的代码。
public class RecommendGoodsAdapter extends RecyclerView.Adapter<RecommendGoodsAdapter.MyViewHolder> {
private Context mContext;
private List<RecommendGoodsInfo> mGoodsInfos;
private SpannableStringUtil mStringUtil;
public RecommendGoodsAdapter(Context mContext, List<RecommendGoodsInfo> mGoodsInfos) {
mStringUtil = new SpannableStringUtil();
this.mContext = mContext;
this.mGoodsInfos = mGoodsInfos;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
return new MyViewHolder(LayoutInflater.from(mContext).inflate(
R.layout.mall_pager_recommend_goods_list_item, viewGroup, false));
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, int i) {
RecommendGoodsInfo goodsInfo = mGoodsInfos.get(i);
myViewHolder.mDraweeView.setImageURI(goodsInfo.getImageUrl());
myViewHolder.mTextDesc.setText(goodsInfo.getDesc());
String price = "¥" + goodsInfo.getSinglePrice() + " x" + goodsInfo.getPeriods() + "期" + "+ ¥" + goodsInfo.getTotalPrice();
SpannableString spannableString = mStringUtil.setMallGoodsPrice(price, 0, getFirstSpaceIndex(price.toCharArray()));
myViewHolder.mTextPrice.setText(spannableString);
String evaluation = "好评率:" + goodsInfo.getEvaluation();
myViewHolder.mTextEvaluation.setText(evaluation);
}
@Override
public int getItemCount() {
return mGoodsInfos.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private SimpleDraweeView mDraweeView;
private TextView mTextDesc;
private TextView mTextPrice;
private TextView mTextEvaluation;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
mDraweeView = itemView.findViewById(R.id.iv_mall_recommend_goods_image);
mTextDesc = itemView.findViewById(R.id.tv_mall_recommend_goods_desc);
mTextPrice = itemView.findViewById(R.id.tv_mall_recommend_goods_price);
mTextEvaluation = itemView.findViewById(R.id.tv_mall_recommend_goods_evaluation);
}
}
private int getFirstSpaceIndex(char[] text) {
for (int i = 0; i < text.length; i++) {
if (text[i] == ' ') {
return i;
}
}
return 0;
}
}
这里的RecyclerView的adapter还是很简单的,同样是重写onCreateViewHolder,onBindViewHolder,并创建自己的ViewHolder去继承RecyclerView.ViewHolder,没啥好说的,都是套路了.
最后附上界面效果
感谢大家的阅读,你的建议就是我前进的动力。热爱生活,热爱开发,愿与大家一同进步。