RecyclerView 分组悬停

第一种原生方法

 

activity布局   ll_top代表要悬停的部分  这里面我放了 图片和文本

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <RelativeLayout
 3     xmlns:android="http://schemas.android.com/apk/res/android"
 4     xmlns:tools="http://schemas.android.com/tools"
 5     android:layout_width="match_parent"
 6     android:layout_height="match_parent"
 7     android:paddingBottom="@dimen/activity_vertical_margin"
 8     android:paddingLeft="@dimen/activity_horizontal_margin"
 9     android:paddingRight="@dimen/activity_horizontal_margin"
10     android:paddingTop="@dimen/activity_vertical_margin"
11     tools:context="com.demon.testservice.ui.RelistActivity">
12 
13     <FrameLayout
14         android:layout_width="match_parent"
15         android:layout_height="match_parent">
16 
17         <android.support.v7.widget.RecyclerView
18             android:id="@+id/recyclerView"
19             android:layout_width="match_parent"
20             android:layout_height="match_parent">
21 
22         </android.support.v7.widget.RecyclerView>
23 
24 
25         <LinearLayout
26             android:id="@+id/ll_top"
27             android:layout_width="match_parent"
28             android:layout_height="wrap_content"
29             android:orientation="vertical">
30 
31 
32             <LinearLayout
33                 android:layout_width="match_parent"
34                 android:layout_height="wrap_content"
35                 android:background="@color/white"
36                 android:gravity="center_vertical"
37                 android:orientation="horizontal">
38 
39                 <ImageView
40                     android:layout_width="30dp"
41                     android:layout_height="30dp"
42                     android:src="@drawable/ic_launcher"/>
43 
44                 <TextView
45                     android:id="@+id/tv_top"
46                     android:layout_width="wrap_content"
47                     android:layout_height="wrap_content"
48                     android:text="name"/>
49 
50             </LinearLayout>
51 
52 
53             <View
54                 android:id="@+id/top_divider"
55                 android:layout_width="match_parent"
56                 android:layout_height="0.2dp"
57                 android:background="#33000000"/>
58 
59         </LinearLayout>
60 
61 
62     </FrameLayout>
63 
64 
65 </RelativeLayout>
View Code

 

item布局    上面和ll_top一样,下面部分是显示一张大图片

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3               android:layout_width="match_parent"
 4               android:layout_height="wrap_content"
 5               android:orientation="vertical"
 6     >
 7 
 8     <LinearLayout
 9         android:layout_width="match_parent"
10         android:layout_height="wrap_content"
11         android:gravity="center_vertical"
12         android:orientation="horizontal"
13         android:background="@color/white"
14         >
15 
16         <ImageView
17             android:layout_width="30dp"
18             android:layout_height="30dp"
19             android:src="@drawable/ic_launcher"/>
20 
21         <TextView
22             android:layout_width="wrap_content"
23             android:layout_height="wrap_content"
24             android:text="name"/>
25 
26     </LinearLayout>
27 
28     <View
29 
30         android:layout_width="match_parent"
31         android:layout_height="0.2dp"
32         android:background="#33000000" />
33 
34 
35     <ImageView
36         android:paddingTop="5dp"
37         android:layout_width="wrap_content"
38         android:layout_height="wrap_content"
39         android:src="@drawable/user"/>
40 
41 
42 </LinearLayout>
View Code

 

activity   设置addOnScrollListener 是关键

 1 public class RelistActivity extends AppCompatActivity {
 2 
 3     @Bind(R.id.recyclerView)
 4     RecyclerView recyclerView;
 5 
 6     @Bind(R.id.ll_top)
 7     LinearLayout ll_top;
 8 
 9     @Bind(R.id.tv_top)
10     TextView tv_top;
11 
12     private int height;
13     private int currentPosition = 0;
14 
15     @Override
16     protected void onCreate(Bundle savedInstanceState) {
17         super.onCreate(savedInstanceState);
18         setContentView(R.layout.activity_relist);
19         ButterKnife.bind(this);
20 
21         final LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this);
22         RelistAdapter adapter=new RelistAdapter();
23 
24         recyclerView.setLayoutManager(linearLayoutManager);
25         recyclerView.setAdapter(adapter);
26 
27 
28         recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
29             @Override
30             public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
31                 super.onScrollStateChanged(recyclerView, newState);
32 
33                 height=ll_top.getHeight();
34 
35             }
36 
37             @Override
38             public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
39                 super.onScrolled(recyclerView, dx, dy);
40                 View view=linearLayoutManager.findViewByPosition(currentPosition+1);
41                 if (view==null)return;
42 
43                 if (view.getTop()<=height){
44                     ll_top.setY(-(height-view.getTop()));
45                 }else {
46                     ll_top.setY(0);
47                 }
48 
49 
50                 if (currentPosition!=linearLayoutManager.findFirstVisibleItemPosition()){
51                     currentPosition=linearLayoutManager.findFirstVisibleItemPosition();
52                     ll_top.setY(0);
53 
54                     tv_top.setText(" "+currentPosition);
55                 }
56             }
57         });
58 
59     }
60 
61 
62 
63 
64 
65 
66 
67     class RelistAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
68 
69 
70         @Override
71         public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
72             View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.item_re,parent,false);
73             return new ReHolder(view);
74         }
75 
76         @Override
77         public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
78 
79         }
80 
81         @Override
82         public int getItemCount() {
83             return 10;
84         }
85 
86         class ReHolder extends RecyclerView.ViewHolder{
87 
88             public ReHolder(View itemView) {
89                 super(itemView);
90                 ButterKnife.bind(this,itemView);
91             }
92         }
93     }
94 
95 
96 }

 

 

 

第二种

timehop/sticky-headers-recyclerview: [UNMAINTAINED] Sticky Headers decorator for Android's RecyclerView  

https://github.com/timehop/sticky-headers-recyclerview

 

这个库好在对adapter改动小,只需要实现就行了

这里用 一个省份城市api 测试 http://apistore.baidu.com/apiworks/servicedetail/990.html

取以下四种数据   并添加一个 string类型的 type

"province": "上海",
"region": "华东地区",
"x": 121.473,
"y": 31.2317

 

CityInfo  是adapter 需要的数据

 1 public class CityInfo {
 2     /*
 3     华东地区  a
 4     华北地区  b
 5     华南地区  c
 6     华中地区  d
 7 
 8     东北地区  e
 9     西北地区  f
10     西南地区  g
11 
12     台港澳地区 h
13      */
14 
15     private String province;
16     private String region;
17     private String type;
18     private double x;
19     private double y;
20 
21     public String getType() {
22         return type;
23     }
24 
25     public void setType(String type) {
26         this.type = type;
27     }
28 
29     public String getProvince() {
30         return province;
31     }
32 
33     public void setProvince(String province) {
34         this.province = province;
35     }
36 
37     public String getRegion() {
38         return region;
39     }
40 
41     public void setRegion(String region) {
42         this.region = region;
43     }
44 
45     public double getX() {
46         return x;
47     }
48 
49     public void setX(double x) {
50         this.x = x;
51     }
52 
53     public double getY() {
54         return y;
55     }
56 
57     public void setY(double y) {
58         this.y = y;
59     }
60 }
View Code

 

获取json依然用rxjava和Retrofit      city对象还是GsonFormat自动解析的  代码就不贴了

public class NetWork {

    private static CityApi cityApi;

    public static CityApi getCityApi(){
        if (cityApi==null){
            Retrofit retrofit=new Retrofit.Builder().baseUrl("http://apis.baidu.com/").addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJavaCallAdapterFactory.create()).build();
            cityApi=retrofit.create(CityApi.class);
        }
        return cityApi;
    }
}
public interface CityApi {
    //http://apis.baidu.com/tngou/factory/province
    @GET("tngou/factory/province")
    rx.Observable<City>getCity(@Header("apikey")String apikey);
}

 

主布局就一个RecyclerView ,悬停布局一个textview ,item 布局三个textview 

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <TextView
 3     android:id="@+id/item_headtv"
 4     xmlns:android="http://schemas.android.com/apk/res/android"
 5     xmlns:tools="http://schemas.android.com/tools"
 6     android:layout_width="match_parent"
 7     android:layout_height="wrap_content"
 8     android:padding="10dp"
 9     tools:text="吸顶文本"
10     android:background="@color/hole_bule"
11     />
headview
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3                 android:layout_width="match_parent"
 4                 android:layout_height="wrap_content"
 5                 android:padding="11dp"
 6                 android:background="@color/blue_semi_transparent_pressed"
 7     >
 8 
 9     <TextView
10         android:id="@+id/tv_sticky_province"
11         android:layout_width="wrap_content"
12         android:layout_height="wrap_content"
13         android:layout_alignParentLeft="true"
14         android:layout_centerVertical="true"
15         android:text="province"
16         />
17 
18     <TextView
19         android:id="@+id/tv_sticky_x"
20         android:layout_width="wrap_content"
21         android:layout_height="wrap_content"
22         android:layout_alignParentRight="true"
23         android:text="X"
24         />
25 
26     <TextView
27         android:id="@+id/tv_sticky_y"
28         android:layout_width="wrap_content"
29         android:layout_height="wrap_content"
30         android:layout_alignParentRight="true"
31         android:layout_below="@+id/tv_sticky_x"
32         android:text="Y"
33         />
34 </RelativeLayout>
item

 

 

adapter   一如既往 继承 RecyclerView.Adapter   并实现  StickyRecyclerHeadersAdapter   重写head的三个方法  

onBindHeaderViewHolder    onCreateHeaderViewHolder  和 RecyclerView的一样 创建分组的view 绑定分组的数据

getHeaderId 稍微有点麻烦 返回值类型为long  所以我在最开始 CityInfo  多设置了一个type  如果api自带那就轻松了 。代码中返回-1的意思是为了把位置为0的item设置成置顶,并不会被分组

 1 public class StickyAdapter2 extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements StickyRecyclerHeadersAdapter {
 2 
 3     private List<CityInfo>list=new ArrayList<CityInfo>();
 4 
 5     public void add(CityInfo object) {
 6         list.add(object);
 7         notifyDataSetChanged();
 8     }
 9 
10     public void addAll(Collection<? extends CityInfo> collection){
11         if (collection!=null){
12             list.addAll(collection);
13             notifyDataSetChanged();
14         }
15     }
16 
17     @Override
18     public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
19         View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.item_stick2,parent,false);
20         return new ItemHolder(view);
21     }
22 
23     @Override
24     public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
25         if (holder instanceof ItemHolder){
26             ItemHolder itemHolder= (ItemHolder) holder;
27             itemHolder.tv_province.setText(list.get(position).getProvince()+"  "+getItem(position));
28 
29             itemHolder.tv_y.setText("Y轴 "+list.get(position).getY());
30             itemHolder.tv_x.setText("X轴 "+list.get(position).getX());
31         }
32 
33     }
34 
35     @Override
36     public long getHeaderId(int position) {
37         if (position==0){
38             return -1;
39         }else {
40             return getItem(position).charAt(0);
41         }
42     }
43 
44     public String getItem(int position) {
45         return list.get(position).getType();
46     }
47 
48     @Override
49     public RecyclerView.ViewHolder onCreateHeaderViewHolder(ViewGroup viewGroup) {
50         View view=LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_headview,viewGroup,false);
51         return new RecyclerView.ViewHolder(view) {
52 
53         };
54     }
55 
56     @Override
57     public void onBindHeaderViewHolder(RecyclerView.ViewHolder holder, int position) {
58         TextView textView = (TextView) holder.itemView;
59         textView.setText(list.get(position).getRegion());
60        // holder.itemView.setBackgroundColor(getRandomColor());
61     }
62 
63     private int getRandomColor() {
64         SecureRandom rgen = new SecureRandom();
65         return Color.HSVToColor(150, new float[]{
66                 rgen.nextInt(359), 1, 1
67         });
68     }
69 
70     @Override
71     public int getItemCount() {
72         return list.size();
73     }
74 
75     class ItemHolder extends RecyclerView.ViewHolder{
76 
77         @Bind(R.id.tv_sticky_province)
78         TextView tv_province;
79         @Bind(R.id.tv_sticky_x)
80         TextView tv_x;
81         @Bind(R.id.tv_sticky_y)
82         TextView tv_y;
83 
84         public ItemHolder(View itemView) {
85             super(itemView);
86             ButterKnife.bind(this,itemView);
87         }
88     }
89 
90 }

 

再看逻辑代码  

StickyRecyclerHeadersDecoration 很重要 一定要设置给recyclerView 不然就不会有head了。   可以发现 它继承了 ItemDecoration,后者通常 是为每个Item视图添加子视图,被用来绘制Divider,可以用,可以不用

添加的head 如果想 相应点击事件,那就要用到 StickyRecyclerHeadersTouchListener,构造参数是 recyclerView 和 StickyRecyclerHeadersDecoration ,得到实例 再用 setOnHeaderClickListener 即可

如果只想获取整个item的点击事件,可以直接用 样品   33到39行 就搞定了

添加item之间的间隙  可以用 这个文件     recyclerView.addItemDecoration(new DividerDecoration(mContext));

第一个数据我自行添加了一个,为了看置顶的效果,后面的list数据 先根据地区信息设置了我需要的type  ,然后进行了一下根据type字母的排序,不然传进去list很乱

 

  1 public class Sticky2Activity extends BaseActivity {
  2 
  3     @Bind(R.id.rcv_stick)
  4     RecyclerView recyclerView;
  5 
  6     private List<CityInfo> list = new ArrayList<CityInfo>();
  7     private StickyAdapter2 adapter;
  8     private StickyRecyclerHeadersDecoration  headersDecoration;
  9 
 10     @Override
 11     protected void onCreate(Bundle savedInstanceState) {
 12         super.onCreate(savedInstanceState);
 13         setContentView(R.layout.activity_sticky2);
 14         ButterKnife.bind(this);
 15         adapter = new StickyAdapter2();
 16         headersDecoration=new StickyRecyclerHeadersDecoration(adapter);
 17 
 18         recyclerView.setLayoutManager(new LinearLayoutManager(mContext));
 19         recyclerView.setAdapter(adapter);
 20        // recyclerView.addItemDecoration(new StickyRecyclerHeadersDecoration(adapter));
 21         recyclerView.addItemDecoration(headersDecoration);
 22         recyclerView.setItemAnimator(new DefaultItemAnimator());
 23         recyclerView.addItemDecoration(new DividerDecoration(mContext));
 24 
 25         StickyRecyclerHeadersTouchListener headersTouchListener=new StickyRecyclerHeadersTouchListener(recyclerView,headersDecoration);
 26         headersTouchListener.setOnHeaderClickListener(new StickyRecyclerHeadersTouchListener.OnHeaderClickListener() {
 27             @Override
 28             public void onHeaderClick(View view, int position, long headerId) {
 29                 showToast("Header position: " + position + ", id: " + headerId);
 30             }
 31         });
 32 
 33         recyclerView.addOnItemTouchListener(headersTouchListener);
 34         recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(mContext, new RecyclerItemClickListener.OnItemClickListener() {
 35             @Override
 36             public void onItemClick(View view, int position) {
 37                 showToast("position "+position);
 38             }
 39         }));
 40 
 41 
 42         NetWork.getCityApi().getCity("f44bd76826571234e2616746eabf3c3c").subscribeOn(Schedulers.io()).observeOn
 43                 (AndroidSchedulers.mainThread()).subscribe(new Action1<City>() {
 44 
 45             @Override
 46             public void call(City city) {
 47                 if (city.isStatus()) {
 48                     int size = city.getTngou().size();
 49                     CityInfo info = new CityInfo();
 50                     info.setProvince("USA");
 51                     info.setRegion("西南地区");
 52                     info.setX(20.032);
 53                     info.setY(20.032);
 54                     info.setType("a");
 55                     list.add(info);
 56 
 57                     for (int i = 0; i < size; i++) {
 58                         City.TngouBean bean = city.getTngou().get(i);
 59                         CityInfo cityInfo = new CityInfo();
 60                         cityInfo.setProvince(bean.getProvince());
 61                         cityInfo.setRegion(bean.getRegion());
 62                         cityInfo.setX(bean.getX());
 63                         cityInfo.setY(bean.getY());
 64                         cityInfo.setType(settype(bean.getRegion()));
 65                         list.add(cityInfo);
 66                     }
 67                     Collections.sort(list, new Comparator<CityInfo>() {
 68                         @Override
 69                         public int compare(CityInfo lhs, CityInfo rhs) {
 70                             String a=lhs.getType();
 71                             String b=rhs.getType();
 72                             return a.compareToIgnoreCase(b);
 73                         }
 74                     });
 75                     adapter.addAll(list);
 76                 }
 77             }
 78         });
 79     }
 80 
 81     private String settype(String region) {
 82         switch (region) {
 83             case "华东地区":
 84                 return "a";
 85             case "华北地区":
 86                 return "b";
 87             case "华南地区":
 88                 return "c";
 89             case "华中地区":
 90                 return "d";
 91             case "东北地区":
 92                 return "e";
 93             case "西北地区":
 94                 return "f";
 95             case "西南地区":
 96                 return "g";
 97             default:
 98             case "台港澳地区":
 99                 return "h";
100         }
101     }
102 }

 

FastAdapter 这个貌似也不错 以后学习

 

 

转载于:https://www.cnblogs.com/demon9/p/5737568.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值