横向滑动类listview 带回弹效果

我们都知道,Android里面有个listview可以上下滑动,还可以设置各种滑动效果,但是对横向滑动的支持比较少,最近做了个demo能够横向滑动并且能使每个item完整显示。横向滑动的有几种方式:

  • HorizontalScrollView 这个是比较新的一个控件,本文就是基于此控件实现的效果参考地址
  • ViewPager 这个也能实现横向滑动但只能显示一个页面 ,可以实现多个同时显示但比较麻烦
  • 已经废弃的Gallery 也可以实现横向滑动 ,但是效果不佳不推荐使用
  • 还可以自定义ScrollView这个方法也可以实现,有兴趣的读者可以试一下
    基本就是以上几种方式实现横向滑动

实现

HorizontalScrollView 的介绍在这里就不赘述了,不了解的朋友可以参考这篇文章
概述:既然是基于HorizontalScrollView 来实现这个控件,那么横向滑动已经解决了,但是如何使其滑动完整显示一个item呢?因此需要拿到已经滑动的距离或者位置再进行调整使其完整显示每一个Item,而正好HorizontalScrollView 中有一个回调的方法setOnScrollListener 实现这个借口就可以拿到item(第一个item)滑动的偏移位置,还可以监听到滑动的状态RecyclerView.SCROLL_STATE_IDLE:// 停止滑动
下面是具体实现代码:

代码

 <android.support.v7.widget.RecyclerView
            android:id="@+id/rvContainer"
            android:layout_width="match_parent"
            android:layout_height="130px"
            android:layout_marginRight="60dp"
            android:scrollbars="none" />

这个控件是API21才有的,所以为了向下兼容我们采取的是支持包方式,这个控件可以在SDK中找到,具体方法可以百度,android.support.v7.widget.RecyclerView

这个是item的xml文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="70px"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/image_item"
        android:layout_marginTop="6dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:scaleType="center" >
    </ImageView>

    <TextView
        android:id="@+id/text_item"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="10px"
        android:text="Bbb" />

</LinearLayout>

在Activity中使用:


    HeadRecyclerViewAdapter adapter = new HeadRecyclerViewAdapter(this, headDataList);
        rvContainer.setAdapter(adapter);
        LinearLayoutManager ll = new LinearLayoutManager(this);//这个是必须的,是设置是横向还是竖向滑动
        ll.setOrientation(LinearLayoutManager.HORIZONTAL);//横向
        rvContainer.setLayoutManager(ll);
        rvContainer.setOnScrollListener(new RecyclerView.OnScrollListener() {
            private int totalDy = 0;
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {//这个是状态监听
                super.onScrollStateChanged(recyclerView, newState);
                switch (newState) {
                case RecyclerView.SCROLL_STATE_IDLE:// 停止滑动状态
                    int scrollX = offX % weight;
                    int scroll = 0;
                    if (scrollX > weight / 2) {
                        scroll = weight - scrollX;
                    } else {
                        scroll = -scrollX;
                    }
                    rvContainer.smoothScrollBy(scroll, 0);//如果不用smoothScrollBy()方法就没有平缓滑动效果
                    L.d("dip", "scroll:" + scroll + " diff:" + scrollX + "  offX:" + offX);
                    break;
                default:
                    break;
                }
            }
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {//这个回调很重要,这个dx,dy 表示的是偏移量,把所有偏移量累加即可得到滑动的总距离,注意值有正负表示左右滑动
                L.d(L.TAG_TEST, "x:" + dx + "  y:" + dy);
                offX += dx;
            }
        });

Adapter




import java.util.List;

import android.app.ActivityOptions;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.StateListDrawable;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

/**
*RecyclerView.Adapter这个是比较新的adapter适配器,这个适配器与普通的listview adapter有点不一样具体如下的代码
*/
public class HeadRecyclerViewAdapter extends
        RecyclerView.Adapter<HeadRecyclerViewAdapter.RCLViewHolder> {
    private List<XMLParserDataItem> headDataList;
    private Context context;
    private OnItemClickLitener itemClickLitener;

    // Provide a reference to the type of views that you are using
    // (custom viewholder)
    public class RCLViewHolder extends RecyclerView.ViewHolder {
        public TextView mTextView;
        public ImageView src;

        public RCLViewHolder(ViewGroup v) {
            super(v);

        }
    }

    public void setOnItemClickLitener(OnItemClickLitener itemClickLitener) {
        this.itemClickLitener = itemClickLitener;
    }

    public interface OnItemClickLitener {
        void onItemClick(View view, int position);
    }

    // Provide a suitable constructor (depends on the kind of dataset)
    public HeadRecyclerViewAdapter(Context context, List<XMLParserDataItem> headDataList) {
        this.headDataList = headDataList;
        this.context = context;
    }


    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return headDataList.size();
    }
// Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(RCLViewHolder holder, final int position) {

        holder.mTextView.setText(headDataList.get(position).getName() + "");
        StateListDrawable[] ls = ViewInflater.inflater(context, headDataList.get(position));
        if (ls != null) {
            holder.src.setImageDrawable(ls[0]);
            holder.src.setBackground(ls[1]);
            holder.src.setTag(headDataList.get(position).getComponentName());
            final int p = position;
            holder.src.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (itemClickLitener != null) {
                        itemClickLitener.onItemClick(v, position);
                    }
                    Toast.makeText(context, "you has click me ! " + position, Toast.LENGTH_SHORT)
                            .show();

                }
            });
        }

    }

// Create new views (invoked by the layout manager)
    @Override
    public RCLViewHolder onCreateViewHolder(ViewGroup parent, int position) {
        // create a new view
        ViewGroup v = (ViewGroup) LayoutInflater.from(parent.getContext()).inflate(
                R.layout.recycler_view_item, parent, false);
        ImageView imageView = (ImageView) v.findViewById(R.id.image_item);
        TextView tv = (TextView) v.findViewById(R.id.text_item);
        RCLViewHolder vh = new RCLViewHolder(v);
        vh.mTextView = tv;
        vh.src = imageView;

        return vh;
    }

}

最后,之前有个大神提供一个思路使用SoccllView 自己感觉比较难实现,没去动手,后来发现这个HorizontalScrollView 比较有优势,他自己就实现了缓存以及回收。但是也有一个不一样的地方,就是adapter有所变化了。但是我觉得这个也是一个好的方式,他强制你实现数据与view分离,我本来想直接将view list传入adapter后来发现失败了,因为它只有这个onCreateViewHolder方法创建视图,而这个创建的方式没有position参数,所以不能根据这个position创建返回指定的view。它跟getView方法有所不同;
总结,不要重复发明轮子,除非你想创造“轮子”;

快捷键

  • 加粗 Ctrl + B
  • 斜体 Ctrl + I
  • 引用 Ctrl + Q
  • 插入链接 Ctrl + L
  • 插入代码 Ctrl + K
  • 插入图片 Ctrl + G
  • 提升标题 Ctrl + H
  • 有序列表 Ctrl + O
  • 无序列表 Ctrl + U
  • 横线 Ctrl + R
  • 撤销 Ctrl + Z
  • 重做 Ctrl + Y
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值