那天逛支付宝的时候看到了如下的界面:
之前书上学的recyclerview的用法讲得太简单了,数据这块不是按着每一个子项的单独设置的,于是想着模仿这个界面练练手,开始弄的时候是感觉有难度的,也是网上各种看资料什么的,折腾了一两天,终于弄好了,效果图如下:
图片实在找不到一模一样的了,其它的大致上感觉还是可以的吧
布局的样式分成了3种,最上边的是标题样式,另外两种大同小异吧,但还是单独弄了3种子项的布局文件
标题布局:
<?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:layout_marginBottom="3dp"
android:background="#F7F7F7">
<TextView
android:id="@+id/bigtitle_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="9dp"
android:layout_marginTop="17dp"
android:textStyle="bold"
android:textSize="19dp"
android:textColor="#343434"/>
<TextView
android:id="@+id/smalltitle_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12dp"
android:textColor="#999999"
android:layout_marginLeft="6dp"
android:layout_marginTop="17dp"/>
</LinearLayout>
第一种子项布局:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
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="wrap_content"
android:layout_margin="4dp"
app:cardCornerRadius="5dp"
app:cardElevation="0dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/image4"
android:layout_width="105dp"
android:layout_height="100dp"
android:layout_alignParentLeft="true"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="8dp"
app:riv_border_color="#FFFFFF"
app:riv_border_width="1dp"
app:riv_corner_radius="3dp"/>
<LinearLayout
android:orientation="vertical"
android:layout_marginTop="11dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/image4">
<TextView
android:id="@+id/first_view1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#343434"
android:textStyle="bold"
android:textSize="14dp"/>
<TextView
android:id="@+id/first_view2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textSize="12dp"
android:textColor="#E93929"/>
<LinearLayout
android:layout_marginTop="9dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/first_view3"
android:textSize="10dp"
android:background="@drawable/textview_border"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/first_view4"
android:textSize="10dp"
android:layout_marginLeft="5dp"
android:background="@drawable/textview_border"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<TextView
android:id="@+id/first_view5"
android:textSize="10dp"
android:layout_marginTop="7dp"
android:textColor="#EC7F44"
android:background="@drawable/textview_border_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<TextView
android:id="@+id/first_view6"
android:textSize="13dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginTop="37dp"
android:layout_marginRight="10dp"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
第二种子项的布局:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
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="wrap_content"
android:layout_margin="4dp"
app:cardCornerRadius="5dp"
app:cardElevation="0dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/image6"
android:layout_width="105dp"
android:layout_height="100dp"
android:layout_alignParentLeft="true"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="8dp"
app:riv_border_color="#FFFFFF"
app:riv_border_width="1dp"
app:riv_corner_radius="3dp"/>
<LinearLayout
android:orientation="vertical"
android:layout_marginTop="11dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/image6">
<TextView
android:id="@+id/second_view1"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:textColor="#343434"
android:maxLines="1"
android:ellipsize="end"
android:textStyle="bold"
android:textSize="14dp"/>
<LinearLayout
android:layout_marginTop="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/second_view2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:textStyle="bold"
android:textColor="#E93929"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#E93929"
android:textSize="12dp"
android:text="元"/>
<TextView
android:id="@+id/second_view3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12dp"
android:layout_marginLeft="3dp"/>
</LinearLayout>
<TextView
android:id="@+id/second_view4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textColor="#E93929"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp">
<ImageView
android:layout_width="14dp"
android:layout_height="14dp"
android:layout_marginTop="2dp"
android:background="@drawable/location"/>
<TextView
android:id="@+id/second_view5"
android:layout_marginLeft="1dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/second_view6"
android:textSize="13dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginTop="40dp"
android:layout_marginRight="10dp"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
主布局:
<?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"
android:orientation="vertical"
android:background="#F7F7F7"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"/>
</LinearLayout>
某些子控件的样式文件就不放了,无非就是文本再加个方框,设置好相应的文件之后再把对应的文件设置成文本的背景即可
对应的viewholder类也有三个,不过都类似,都是在里边获取相应的实例,这里放出其中一个,代码如下:
package com.example.wechattest;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
public class FirstViewHolder extends RecyclerView.ViewHolder {
public ImageView firstImage;
public TextView firstText1;
public TextView firstText2;
public TextView firstText3;
public TextView firstText4;
public TextView firstText5;
public TextView firstText6;
public FirstViewHolder(View itemView) {
super(itemView);
firstImage = itemView.findViewById(R.id.image4);
firstText1 = itemView.findViewById(R.id.first_view1);
firstText2 = itemView.findViewById(R.id.first_view2);
firstText3 = itemView.findViewById(R.id.first_view3);
firstText4 = itemView.findViewById(R.id.first_view4);
firstText5 = itemView.findViewById(R.id.first_view5);
firstText6 = itemView.findViewById(R.id.first_view6);
}
}
还需要建一个RecyclerViewItemData类,后续要用来进行相应数据类型的判断然后加载对应的布局样式,代码如下:
package com.example.wechattest;
public class RecyclerViewItemData<T> {
T t;
int dataType;
public RecyclerViewItemData() {
}
public RecyclerViewItemData(T t,int dataType) {
this.t = t;
this.dataType = dataType;
}
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
public int getDataType() {
return dataType;
}
public void setDataType(int dataType) {
this.dataType = dataType;
}
}
接下来是整个页面最重要的一个类,在这里会进行数据的设置以及根据不用数据类型来加载不同的布局样式,RecyclerViewAdapter:
package com.example.wechattest;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.v7.widget.RecyclerView;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.text.style.StrikethroughSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import java.util.ArrayList;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int TYPE_FIRST = 0; // 第一种子项布局
private static final int TYPE_SECOND = 1; // 第二种子项布局
private static final int TYPE_TITLE = 2; // 标题布局
private ArrayList<RecyclerViewItemData> dataList;
public RecyclerViewAdapter(ArrayList<RecyclerViewItemData> dataList) {
this.dataList = dataList;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {
// 如果viewType是第一种样式的类型,则创建FirstViewHolder型viewholder
if (viewType == TYPE_FIRST) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.alipay_item,parent,false);
FirstViewHolder viewHolder = new FirstViewHolder(view);
return viewHolder;
}
// 如果viewType是第二种样式的类型,则创建SecondViewHolder型viewholder
if (viewType == TYPE_SECOND) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.alipay_item_2,parent,false);
SecondViewHolder viewHolder = new SecondViewHolder(view);
return viewHolder;
}
// 如果viewType是标题的类型,则创建TitleViewHolder型viewholder
if (viewType == TYPE_TITLE) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.alipay_item_title,parent,false);
TitleViewHolder viewHolder = new TitleViewHolder(view);
return viewHolder;
}
return null;
}
// 绑定数据
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder,int position) {
// 如果holder是TitleViewHolder的实例
if (holder instanceof TitleViewHolder) {
// AlipayItemtitle alipayItemtitle = (AlipayItemtitle) dataList.get(position).getT();
// 设置对应位置处子项的数据
if (position == 0) {
((TitleViewHolder) holder).bigTitle.setText("为你定制");
((TitleViewHolder) holder).smallTitle.setText("惬意时光,不如好好放松一下?");
}
}
// 如果holder是FirstViewHolder的实例
if (holder instanceof FirstViewHolder) {
// AlipayItemf alipayItemf = (AlipayItemf) dataList.get(position).getT();
if (position == 1) {
((FirstViewHolder) holder).firstImage.setScaleType(ImageView.ScaleType.FIT_XY);
((FirstViewHolder) holder).firstImage.setImageResource(R.drawable.banana);
((FirstViewHolder) holder).firstText1.setText("胜咖啡(友谊商业广场店)");
((FirstViewHolder) holder).firstText2.setText("人气97");
((FirstViewHolder) holder).firstText3.setText("停车位");
((FirstViewHolder) holder).firstText4.setText("解放西美食榜第5名");
((FirstViewHolder) holder).firstText5.setText("8元代金券");
((FirstViewHolder) holder).firstText6.setText("1.0km");
} else if (position == 2) {
((FirstViewHolder) holder).firstImage.setScaleType(ImageView.ScaleType.FIT_XY);
((FirstViewHolder) holder).firstImage.setImageResource(R.drawable.pear);
((FirstViewHolder) holder).firstText1.setText("鱼乐缘(友谊阳光城店)");
((FirstViewHolder) holder).firstText2.setText("人气95");
((FirstViewHolder) holder).firstText3.setText("停车位");
((FirstViewHolder) holder).firstText4.setText("龙华区川菜榜第3名");
StringBuilder stringBuilder = new StringBuilder("148元 208元 | 超值精选套餐");
SpannableString spannableString = new SpannableString(stringBuilder);
spannableString.setSpan(new StrikethroughSpan(),5,9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(new ForegroundColorSpan(Color.parseColor("#F4B593")),5,9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
((FirstViewHolder) holder).firstText5.setText(spannableString);
((FirstViewHolder) holder).firstText6.setText("1.2km");
}
}
// 如果holder是SecondViewHolder的实例
if (holder instanceof SecondViewHolder) {
// AlipayItems alipayItems = (AlipayItems) dataList.get(position).getT();
if (position == 3) {
((SecondViewHolder) holder).secondImage.setScaleType(ImageView.ScaleType.FIT_XY);
((SecondViewHolder) holder).secondImage.setImageResource(R.drawable.pineapple);
((SecondViewHolder) holder).secondText1.setText("单人套餐,提供免费停车位。");
((SecondViewHolder) holder).secondText2.setText("10.90");
((SecondViewHolder) holder).secondText3.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
((SecondViewHolder) holder).secondText3.setText("20元");
((SecondViewHolder) holder).secondText4.setText("6小时内已售15件");
((SecondViewHolder) holder).secondText5.setText("华莱士(龙华店)");
((SecondViewHolder) holder).secondText6.setText("270m");
}
if (position == 4) {
((SecondViewHolder) holder).secondImage.setScaleType(ImageView.ScaleType.FIT_XY);
((SecondViewHolder) holder).secondImage.setImageResource(R.drawable.apple);
((SecondViewHolder) holder).secondText1.setText("单人套餐3选1。");
((SecondViewHolder) holder).secondText2.setText("12");
((SecondViewHolder) holder).secondText3.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
((SecondViewHolder) holder).secondText3.setText("20元");
((SecondViewHolder) holder).secondText4.setText("12小时内已售28件");
((SecondViewHolder) holder).secondText5.setText("华莱士(市一中店)");
((SecondViewHolder) holder).secondText6.setText("1.0km");
}
if (position == 5) {
((SecondViewHolder) holder).secondImage.setScaleType(ImageView.ScaleType.FIT_XY);
((SecondViewHolder) holder).secondImage.setImageResource(R.drawable.orange);
((SecondViewHolder) holder).secondText1.setText("2份阿方索芒果冰淇淋花筒/华丽美食等");
((SecondViewHolder) holder).secondText2.setText("12.50");
((SecondViewHolder) holder).secondText3.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
((SecondViewHolder) holder).secondText3.setText("16元");
((SecondViewHolder) holder).secondText4.setText("6小时内已售1260件");
((SecondViewHolder) holder).secondText5.setText("肯德基(友谊餐厅)");
((SecondViewHolder) holder).secondText6.setText("919m");
}
if (position == 6) {
((SecondViewHolder) holder).secondImage.setScaleType(ImageView.ScaleType.FIT_XY);
((SecondViewHolder) holder).secondImage.setImageResource(R.drawable.cherry);
((SecondViewHolder) holder).secondText1.setText("单人套餐,提供免费WiFi。");
((SecondViewHolder) holder).secondText2.setText("25");
((SecondViewHolder) holder).secondText3.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
((SecondViewHolder) holder).secondText3.setText("37元");
((SecondViewHolder) holder).secondText4.setText("12小时内已售5件");
((SecondViewHolder) holder).secondText5.setText("尊宝比萨(国贸店)");
((SecondViewHolder) holder).secondText6.setText("846m");
}
if (position == 7) {
((SecondViewHolder) holder).secondImage.setScaleType(ImageView.ScaleType.FIT_XY);
((SecondViewHolder) holder).secondImage.setImageResource(R.drawable.grape);
((SecondViewHolder) holder).secondText1.setText("下午茶 (脆皮炸鸡+鲜萃柠檬汁很香甜)");
((SecondViewHolder) holder).secondText2.setText("16");
((SecondViewHolder) holder).secondText3.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
((SecondViewHolder) holder).secondText3.setText("23元");
((SecondViewHolder) holder).secondText4.setText("9小时内已售43件");
((SecondViewHolder) holder).secondText5.setText("德克士dicos(万国)");
((SecondViewHolder) holder).secondText6.setText("849m");
}
if (position == 8) {
((SecondViewHolder) holder).secondImage.setScaleType(ImageView.ScaleType.FIT_XY);
((SecondViewHolder) holder).secondImage.setImageResource(R.drawable.mango);
((SecondViewHolder) holder).secondText1.setText("西西里风情肉酱满溢千层面");
((SecondViewHolder) holder).secondText2.setText("36");
((SecondViewHolder) holder).secondText3.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
((SecondViewHolder) holder).secondText3.setText("46元");
((SecondViewHolder) holder).secondText4.setText("6小时内已售116件");
((SecondViewHolder) holder).secondText5.setText("必胜客(大同餐厅)");
((SecondViewHolder) holder).secondText6.setText("922m");
}
}
}
@Override
public int getItemViewType(int position) {
if (0 == dataList.get(position).getDataType()) {
return TYPE_FIRST; // 第一种样式的子项
} else if (1 == dataList.get(position).getDataType()) {
return TYPE_SECOND; // 第二种样式的子项
} else if (2 == dataList.get(position).getDataType()) {
return TYPE_TITLE; // 标题子项
} else {
return 0;
}
}
@Override
public int getItemCount() {
return dataList.size();
}
}
最后是主活动MainActivity:
package com.example.wechattest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private ArrayList<RecyclerViewItemData> dataList;
RecyclerView recyclerView;
LinearLayoutManager linearLayoutManager;
RecyclerViewAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_alipay);
recyclerView = findViewById(R.id.recycler_2);
dataList = new ArrayList<>();
/**
* 由于本例中未涉及到相关数据的输入及获取显示,所以前边的数据可以随意设置,重点是dataType的数据得设置正确,
* RecyclerViewAdapter中会根据相应的数据来加载对应的布局样式;另外add()方法添加的数据集合需要按照实际显示
* 需求来依次设置,否则每一个子项对应的样式会乱掉
*/
dataList.add(new RecyclerViewItemData(new AlipayItemtitle("",""),2));
dataList.add(new RecyclerViewItemData(new AlipayItemf(1,"","","","","",""),0));
dataList.add(new RecyclerViewItemData(new AlipayItemf(1,"","","","","",""),0));
dataList.add(new RecyclerViewItemData(new AlipayItems(1,"","","","","",""),1));
dataList.add(new RecyclerViewItemData(new AlipayItems(1,"","","","","",""),1));
dataList.add(new RecyclerViewItemData(new AlipayItems(1,"","","","","",""),1));
dataList.add(new RecyclerViewItemData(new AlipayItems(1,"","","","","",""),1));
dataList.add(new RecyclerViewItemData(new AlipayItems(1,"","","","","",""),1));
dataList.add(new RecyclerViewItemData(new AlipayItems(1,"","","","","",""),1));
linearLayoutManager = new LinearLayoutManager(this);
adapter = new RecyclerViewAdapter(dataList);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setAdapter(adapter);
}
}
开始弄的时候觉得还是挺难弄的,弄完之后一遍遍再梳理逻辑的时候感觉也并不是太难,主要是一些细节挺费时间的,要照着模仿界面的间距一点点调试,调试完运行看结果,这个挺需要耐心的,有些点也是在做的过程中慢慢学习到了,比如图片的四个角要设置弧度,这个看了许多资料,大多是要进行自定义view的设置,后边找到了简洁的办法,运用RoundedImageView类库仅仅几行代码就解决了,还有文本设置删除线的问题,一开始只找到了整段文本设置删除线的办法,后边因为有部分文本设置删除线的需求,也是好好研究了一番,不过关于删除线的样式问题,后续有空还得再研究一下,标题和下边内容一起滚动的问题也纠结了许久,一开始用的coordinatorlayout,结果不是自己想要的,后来经过指点才知道也弄成recyclerview的其中一个子项,结果还算完美吧