使用RecyclerView实现GridView和ListView混排的效果
2016-08-19 10:25
645 查看
单位在做股票相关的app,美工切出一个图,是一个GridView和ListView混排的效果图,而且在滚动的时候,还要实现相关类别名有推动的效果,如下图:
录制的效果不是很好,因为csdn只能上传2M,所以点击的效果没有实现。下面会下载的地址。可以下载看一下。现在说一下实现的思路。个人感觉不是很好,只是为了完成功能,如果你有更好的思路或是方法,希望能告诉我。
1,RecyclerView虽然很灵活,可是也没有GridView与listView混排的功能。
2,GridLayoutManager有一个方法setSpanSizeLookup,可以设置GridView中每项的所占的比例。
3,类别项,GridView项,ListView项的布局都不一样,这个我们只能设计viewType来处理。
4,根据设计思路类别项,GridView项,ListView项点击是会跳转到不同的页面的。
好了,根据这个思路和步骤我们开始我们的代码吧。
activity_main.xml,主布局,这个没什么可说的,就是一个RecyclerView控件,外加一个用来显示类别的布局。
下面我们设置一下,三种项的布局,类别项,GridView项,ListView项
activity_pinned_titleitem.xml 类别项
activity_pinned_griditem.xml GridView项
activity_pinned_listitem.xml listView项布局
根据上面的图,我们做一个测试model文件。
myTestModel.xml
好,布局和model完成,我们来设计一下我们的adpter
PinnedRecyAdapter.java
这里没有什么可以说的,就是根据viewtype的不同,显示三个不同的布局,同时定义了点击事件,这里注意点击事件的第三个变量,type它是用来判断我点的是哪种布局,前台根据这个来判断,要跳转的页面。
MainActivity.java文件,主程序,里面我写了注解。
最后的结果就是上图所显示的结果,这里我要说明一点,这个完全是根据设计需求做出来,感觉不是很好,而且相对来说比较死。如果你有好的方法,希望能告诉我,大家一起进步。期待你的回信。
下载地址:下载地址
录制的效果不是很好,因为csdn只能上传2M,所以点击的效果没有实现。下面会下载的地址。可以下载看一下。现在说一下实现的思路。个人感觉不是很好,只是为了完成功能,如果你有更好的思路或是方法,希望能告诉我。
1,RecyclerView虽然很灵活,可是也没有GridView与listView混排的功能。
2,GridLayoutManager有一个方法setSpanSizeLookup,可以设置GridView中每项的所占的比例。
3,类别项,GridView项,ListView项的布局都不一样,这个我们只能设计viewType来处理。
4,根据设计思路类别项,GridView项,ListView项点击是会跳转到不同的页面的。
好了,根据这个思路和步骤我们开始我们的代码吧。
activity_main.xml,主布局,这个没什么可说的,就是一个RecyclerView控件,外加一个用来显示类别的布局。
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.cg.pinnedsectionrecyclerview.MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/recy_pinned" android:layout_width="match_parent" android:layout_height="match_parent" /> <LinearLayout android:id="@+id/title_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#ff6688"> <TextView android:id="@+id/txt_Title" android:layout_width="wrap_content" android:layout_height="50dp" android:gravity="center_vertical" android:text="行业版块"/> </LinearLayout> </RelativeLayout>
下面我们设置一下,三种项的布局,类别项,GridView项,ListView项
activity_pinned_titleitem.xml 类别项
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/linear_t" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#ff6688"> <TextView android:id="@+id/txt_pTitle" android:layout_width="wrap_content" android:layout_height="50dp" android:gravity="center_vertical"/> </LinearLayout>
activity_pinned_griditem.xml GridView项
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/linear_g" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:gravity="center" android:paddingTop="5dp" android:paddingBottom="5dp"> <TextView android:id="@+id/txt_pGName" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="股名" android:textSize="16dp" android:gravity="center"/> <TextView android:id="@+id/txt_pGValue1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="+4.12%" android:textSize="14dp" android:textColor="#ff4433" android:gravity="center"/> <TextView android:id="@+id/txt_pGValue2" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="好名字 +4.12%" android:textSize="12dp" android:textColor="#ff4433" android:gravity="center"/> </LinearLayout>
activity_pinned_listitem.xml listView项布局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rela_l" android:layout_width="match_parent" android:layout_height="45dp" android:orientation="horizontal" android:gravity="center_vertical"> <TextView android:id="@+id/txt_pLName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="股名" android:textSize="16dp" android:layout_marginLeft="5dp"/> <TextView android:id="@+id/txt_pLValue2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="+4.12%" android:textSize="12dp" android:textColor="#ff4433" android:layout_alignParentRight="true" android:layout_marginRight="10dp"/> <TextView android:id="@+id/txt_pLValue1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="+4.12%" android:textSize="14dp" android:textColor="#ff4433" android:layout_marginRight="25dp" android:layout_toLeftOf="@+id/txt_pLValue2"/> </RelativeLayout>
根据上面的图,我们做一个测试model文件。
myTestModel.xml
package com.example.cg.pinnedsectionrecyclerview.models; /** * 测试数据结构 * 作者:cg * 时间:2016/8/18 0018 上午 11:01 */ public class myTestModel { private String title; //类别,标题 private String name; //股票名称 private String value1; //涨跌值1 private String value2; //涨跌值2 private int type; //数据显示的类别 1:Grid布局数据 2:List布局数据 3:类别布局数据 private int sordid; //分类的顺序值,此值为信息所属类别的顺序值 public myTestModel() { } public myTestModel(String title, String name, String value1, String value2,int type,int sordid) { this.title = title; this.name = name; this.value1 = value1; this.value2 = value2; this.type = type; this.sordid = sordid; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getValue1() { return value1; } public void setValue1(String value1) { this.value1 = value1; } public String getValue2() { return value2; } public void setValue2(String value2) { this.value2 = value2; } public int getType() { return type; } public void setType(int type) { this.type = type; } public int getSordid() { return sordid; } public void setSordid(int sordid) { this.sordid = sordid; } }
好,布局和model完成,我们来设计一下我们的adpter
PinnedRecyAdapter.java
package com.example.cg.pinnedsectionrecyclerview.Adapter; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import com.example.cg.pinnedsectionrecyclerview.R; import com.example.cg.pinnedsectionrecyclerview.models.myTestModel; import java.util.List; /** * RecyclerView的Adapter * 作者:cg * 时间:2016/8/18 0018 上午 10:47 */ public class PinnedRecyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private List<myTestModel> list_data; private LayoutInflater inflater; private Context context; public PinnedRecyAdapter(List<myTestModel> list_data, Context context) { this.list_data = list_data; this.inflater = LayoutInflater.from(context); this.context = context; } /** * 定义点击每项的接口,此处只实现了点击,没有实现长按 */ public interface OnItemClickLitener { void OnItemClick(View view, int positon, int type); void OnItemLongClick(View view, int position); } private OnItemClickLitener mOnItemClickLitener; public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener) { this.mOnItemClickLitener = mOnItemClickLitener; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view; RecyclerView.ViewHolder mViewHolder; if(viewType==1) { view = inflater.inflate(R.layout.activity_pinned_griditem, parent, false); mViewHolder = new gViewHolder(view); }else if(viewType==2) { view = inflater.inflate(R.layout.activity_pinned_listitem, parent, false); mViewHolder = new lViewHolder(view); }else { view = inflater.inflate(R.layout.activity_pinned_titleitem, parent, false); mViewHolder = new tViewHolder(view); } return mViewHolder; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { switch (getItemViewType(position)) { case 1: final gViewHolder gHolder = (gViewHolder)holder; gHolder.txt_pGName.setText(list_data.get(position).getName()); gHolder.txt_pGValue1.setText(list_data.get(position).getValue1()); gHolder.txt_pGValue2.setText(list_data.get(position).getValue2()); if(mOnItemClickLitener!=null) { gHolder.linear_g.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //Toast.makeText(context,list_data.get(position).getName(),Toast.LENGTH_SHORT).show(); mOnItemClickLitener.OnItemClick(gHolder.itemView, position,1); } }); } break; case 2: final lViewHolder lHolder = (lViewHolder)holder; lHolder.txt_pLName.setText(list_data.get(position).getName()); lHolder.txt_pLValue1.setText(list_data.get(position).getValue1()); lHolder.txt_pLValue2.setText(list_data.get(position).getValue2()); if(mOnItemClickLitener!=null) { lHolder.rela_l.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //Toast.makeText(context,list_data.get(position).getName(),Toast.LENGTH_SHORT).show(); mOnItemClickLitener.OnItemClick(lHolder.itemView, position,2); } }); } break; case 3: final tViewHolder tHolder = (tViewHolder)holder; tHolder.txt_pTitle.setText(list_data.get(position).getTitle()); if(mOnItemClickLitener!=null) { tHolder.linear_t.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //Toast.makeText(context,list_data.get(position).getName(),Toast.LENGTH_SHORT).show(); mOnItemClickLitener.OnItemClick(tHolder.itemView, position,3); } }); } break; } } @Override public int getItemViewType(int position) { return list_data.get(position).getType(); } @Override public int getItemCount() { return list_data.size(); } /** * 类别形式的布局数据 */ class tViewHolder extends RecyclerView.ViewHolder { LinearLayout linear_t; TextView txt_pTitle; public tViewHolder(View itemView) { super(itemView); linear_t = (LinearLayout)itemView.findViewById(R.id.linear_t); txt_pTitle = (TextView)itemView.findViewById(R.id.txt_pTitle); } } /** * Grid形式的布局数据 */ class gViewHolder extends RecyclerView.ViewHolder { LinearLayout linear_g; TextView txt_pGName; TextView txt_pGValue1; TextView txt_pGValue2; public gViewHolder(View itemView) { super(itemView); linear_g = (LinearLayout)itemView.findViewById(R.id.linear_g); txt_pGName = (TextView)itemView.findViewById(R.id.txt_pGName); txt_pGValue1 = (TextView)itemView.findViewById(R.id.txt_pGValue1); txt_pGValue2 = (TextView)itemView.findViewById(R.id.txt_pGValue2); } } /** * List形式的布局数据 */ class lViewHolder extends RecyclerView.ViewHolder { RelativeLayout rela_l; TextView txt_pLName; TextView txt_pLValue1; TextView txt_pLValue2; public lViewHolder(View itemView) { super(itemView); rela_l = (RelativeLayout)itemView.findViewById(R.id.rela_l); txt_pLName = (TextView)itemView.findViewById(R.id.txt_pLName); txt_pLValue1 = (TextView)itemView.findViewById(R.id.txt_pLValue1); txt_pLValue2 = (TextView)itemView.findViewById(R.id.txt_pLValue2); } } }
这里没有什么可以说的,就是根据viewtype的不同,显示三个不同的布局,同时定义了点击事件,这里注意点击事件的第三个变量,type它是用来判断我点的是哪种布局,前台根据这个来判断,要跳转的页面。
MainActivity.java文件,主程序,里面我写了注解。
package com.example.cg.pinnedsectionrecyclerview; import android.annotation.TargetApi; import android.content.Context; import android.os.Build; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import com.example.cg.pinnedsectionrecyclerview.Adapter.PinnedRecyAdapter; import com.example.cg.pinnedsectionrecyclerview.models.myTestModel; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { //分别定义三种显示格式的值 private static int GridFlag = 1; private static int ListFlag = 2; private static int titleFlag = 3; private Context mContext; private RecyclerView recy_pinned; private List<myTestModel> mDatas; private PinnedRecyAdapter pAdapter; private GridLayoutManager gManager; private LinearLayout titleLayout; private TextView txt_Title; private int lastFirstVisibleItem = -1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mContext = MainActivity.this; initData(); initControls(); } /** * 初始化数据 * 因为这是Grid与list的混排,所以没法将title也就是类别,放到每条记录里,因为Grid类型,没法处理。 * 所以这里我采用的是单独把类别做为一个条记录存入并且给了一个单独的类别3 */ protected void initData() { mDatas = new ArrayList<>(); myTestModel mModel1 = new myTestModel(); mModel1.setTitle("行业版块"); mModel1.setName(""); mModel1.setValue1(""); mModel1.setValue2(""); mModel1.setType(titleFlag); mModel1.setSordid(1); mDatas.add(mModel1); for(int i=0;i<6;i++) { myTestModel mModel = new myTestModel(); mModel.setTitle("行业版块"); mModel.setName("行业版块" + i); mModel.setValue1("+4.23%"); mModel.setValue2("行业股" + i + " 3.24%"); mModel.setType(GridFlag); mModel.setSordid(1); mDatas.add(mModel); } myTestModel mModel2 = new myTestModel(); mModel2.setTitle("概念版块"); mModel2.setName(""); mModel2.setValue1(""); mModel2.setValue2(""); mModel2.setType(titleFlag); mModel2.setSordid(2); mDatas.add(mModel2); for(int i=0;i<6;i++) { myTestModel mModel = new myTestModel(); mModel.setTitle("概念版块"); mModel.setName("概念版块" + i); mModel.setValue1("+5.23%"); mModel.setValue2("概念股" + i + " 5.24%"); mModel.setType(GridFlag); mModel.setSordid(2); mDatas.add(mModel); } myTestModel mModel3 = new myTestModel(); mModel3.setTitle("泸深A股"); mModel3.setName(""); mModel3.setValue1(""); mModel3.setValue2(""); mModel3.setType(titleFlag); mModel3.setSordid(3); mDatas.add(mModel3); for(int i=0;i<10;i++) { myTestModel mModel = new myTestModel(); mModel.setTitle("泸深A股"); mModel.setName("泸深A股" + i); mModel.setValue1("+1.23%"); mModel.setValue2("1.24%"); mModel.setType(ListFlag); mModel.setSordid(3); mDatas.add(mModel); } myTestModel mModel4 = new myTestModel(); mModel4.setTitle("创业版指"); mModel4.setName(""); mModel4.setValue1(""); mModel4.setValue2(""); mModel4.setType(titleFlag); mModel4.setSordid(4); mDatas.add(mModel4); for(int i=0;i<15;i++) { myTestModel mModel = new myTestModel(); mModel.setTitle("创业版指"); mModel.setName("创业版指" + i); mModel.setValue1("+6.23%"); mModel.setValue2("6.24%"); mModel.setType(ListFlag); mModel.setSordid(4); mDatas.add(mModel); } } /** * 初始化控件 */ @TargetApi(Build.VERSION_CODES.M) private void initControls() { titleLayout = (LinearLayout)findViewById(R.id.title_layout); txt_Title = (TextView)findViewById(R.id.txt_Title); recy_pinned = (RecyclerView)findViewById(R.id.recy_pinned); /** * 在这里,我们把LayoutManager设成Grid形式,根据实际情况,这里我设置成三列 * setSpanSizeLookup方法,个人感觉有点像我们xml布局中的layout_weight,它表示Grid中的每项占几个位置 * 在这里,根据实际情况,我们可以得知,类别栏和下面的list形式数据全是每条占满的也就是一个占三个的位置 */ gManager = new GridLayoutManager(this,3); gManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { if (position == 0 || position == 7 || position > 13) { return 3; } else { return 1; } } }); recy_pinned.setLayoutManager(gManager); pAdapter = new PinnedRecyAdapter(mDatas,this); recy_pinned.setAdapter(pAdapter); /** * 这里,我们根据控件的滚动情况,来对菜单栏进行处理。 * 这里可以参看郭霖大神的http://blog.csdn.net/guolin_blog/article/details/9033553 */ recy_pinned.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); //取得当前屏幕可见数据的第一个值 int firstVisibleItem = gManager.findFirstVisibleItemPosition(); //取得当前屏幕可见数据的第一个值的类别值 int section = mDatas.get(firstVisibleItem).getSordid(); //取得当前屏幕可见数据的第一个值的类别值在类别顺序中的下一个类别值 int nextSecPosition = getLastIndex(section); if (firstVisibleItem != lastFirstVisibleItem) { ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) titleLayout.getLayoutParams(); params.topMargin = 0; titleLayout.setLayoutParams(params); txt_Title.setText(mDatas.get(firstVisibleItem).getTitle()); } if (nextSecPosition == firstVisibleItem + 1) { View childView = recyclerView.getChildAt(0); if (childView != null) { int titleHeight = titleLayout.getHeight(); int bottom = childView.getBottom(); ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) titleLayout .getLayoutParams(); if (bottom < titleHeight) { float pushedDistance = bottom - titleHeight; params.topMargin = (int) pushedDistance; titleLayout.setLayoutParams(params); } else { if (params.topMargin != 0) { params.topMargin = 0; titleLayout.setLayoutParams(params); } } } } lastFirstVisibleItem = firstVisibleItem; } }); pAdapter.setOnItemClickLitener(new PinnedRecyAdapter.OnItemClickLitener() { @Override public void OnItemClick(View view, int positon, int type) { if(type==GridFlag) { Toast.makeText(mContext, mDatas.get(positon).getName(), Toast.LENGTH_SHORT).show(); }else if(type==titleFlag) { Toast.makeText(mContext,mDatas.get(positon).getTitle(),Toast.LENGTH_SHORT).show(); }else { Toast.makeText(mContext,mDatas.get(positon).getName(),Toast.LENGTH_SHORT).show(); } } @Override public void OnItemLongClick(View view, int position) { } }); } /** * 根据传入的当前类别值,取出下一个类别的第一条记录的排序号,就是在数据列表中的顺序 * * 这里的值,大家可以根据自己的实际情况去算一下。 * * @param i 当前类别值 * @return 下一个类别的第一条记录的排序号 */ private int getLastIndex(int i) { switch (i) { case 1: return 5; case 2: return 12; case 3: return 25; default: return 0; } } }
最后的结果就是上图所显示的结果,这里我要说明一点,这个完全是根据设计需求做出来,感觉不是很好,而且相对来说比较死。如果你有好的方法,希望能告诉我,大家一起进步。期待你的回信。
下载地址:下载地址
相关文章推荐
- 使用RecyclerView实现ListView,GridView效果
- 使用RecyclerView实现ListView,GridView的效果(上下,左右滑动),拖拽与滑动删除
- RecyclerView实现ListView和GridView的效果
- RecyclerView--实现 ListView,GridView,瀑布流 效果
- RecyclerView的基本用法 (一个控件实现ListView, GridView等效果)+接口回调点击事件
- RecyclerView简单解析使用Xutils实现表格效果和普通listview效果
- 使用RecyclerView实现多行水平分页的GridView效果和ViewPager效果
- 使用RecyclerView实现滑动添加、滑动删除,以及瀑布流、ListView、GridView的转换
- Android中Recyclerview使用1----实现ListView,GridView,瀑布流样式
- ListView实现item的卡片效果(不使用RecyclerView+CardView)
- Android RecyclerView详解之实现 ListView GridView瀑布流效果
- 使用RecyclerView实现电商物流信息的时光轴效果
- RecyclerView实现 gridview效果!
- 在ListView或GridView 中使用到跑马灯滚动效果实现的问题。
- 使用ViewPager+GridView实现横向滑动的效果(一)
- RecyclerView介绍(二)实现ListView的效果
- RecyclerView介绍(三)----实现GridView效果
- Android RecyclerView实现listview效果
- 使用ViewPager+GridView实现横向滑动的效果(二)
- 使用RecyclerView实现带Header和Footer的GridView