RecyclerView点击,移动到中间位置

这篇博客介绍怎样给RecyclerView添加点击事件,点击某一条item,被点击的item能移动到中间位置。

例如我们点击靠右边的03-28那一个item,这个item会自动滑到中间位置,效果如下:
点击滑动到中间

具体实现过程是怎么样的呢?(RecyclerView的使用前面的博客已介绍过,这里就不再赘述了。)

首先,我们在RecyclerView的adapter里,自定义一个接口OnItemClickListener,onBindViewHolder()方法中,给item添加点击事件。示例代码如下:

package com.li.recyclerviewdemo;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
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.TextView;

public class RvAdapter extends RecyclerView.Adapter<RvAdapter.ViewHolder> {

    private Context context;
    private List<TestBeans> datas;
    private RvAdapter.OnItemClickListener onItemClickListener;
    //用来标记点击的item位置,方便设置背景颜色
    private List<Integer> posList = new ArrayList<Integer>();

    public RvAdapter(Context context, List<TestBeans> datas) {
        super();
        this.context = context;
        this.datas = datas;
    }

    public void setOnItemClickListener(RvAdapter.OnItemClickListener listener){
        this.onItemClickListener = listener;
    }

    @Override
    public int getItemCount() {
        return datas == null ? 0 : datas.size();
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, int pos) {
        TestBeans bean = datas.get(pos);
        holder.tvDate.setText(bean.getDateMd());
        holder.tvDay.setText(bean.getDateDay());
        holder.tvPrice.setText(bean.getPrice());

        //设置点击事件的回调
        holder.itemView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if(onItemClickListener != null){
                    int position = holder.getPosition();
                    onItemClickListener.onItemClick(holder.itemView, position);
                    //标记点击的item位置
                    posList.clear();
                    posList.add(position); 
                }
            }
        });

        if(posList.contains(pos)){
            holder.itemView.setBackgroundColor(context.getResources().getColor(R.color.green));
        }else{
            holder.itemView.setBackgroundColor(context.getResources().getColor(R.color.grey));
        }
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup arg0, int arg1) {
        View v = LayoutInflater.from(arg0.getContext()).inflate(
                R.layout.rv_adapter_item, arg0, false);
        ViewHolder vh = new ViewHolder(v);
        return vh;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        TextView tvDate;
        TextView tvDay;
        TextView tvPrice;

        public ViewHolder(View itemView) {
            super(itemView);
            tvDate = (TextView) itemView.findViewById(R.id.tvDate);
            tvDay = (TextView) itemView.findViewById(R.id.tvDay);
            tvPrice = (TextView) itemView.findViewById(R.id.tvPrice);
        }
    }

    /**
     * 自定义的点击事件接口
     * @author lish
     */
    public interface OnItemClickListener{
        void onItemClick(View view, int position);
//      void onItemLongClick(View view, int position); //长按
    }
}

MainActivity.java 中,adapter添加点击事件,然后被点击的item移动到中间位置。

adapter.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                Toast.makeText(MainActivity.this, "-->" + position, Toast.LENGTH_SHORT).show();
                moveToMiddle(view);
                adapter.notifyDataSetChanged();
            }
        });

View移动的方法:

    /**
     * 滚动到中间位置
     * @param clkView  被点击的View
     */
    public void moveToMiddle(View clkView){
        int itemWidth = clkView.getWidth();
        int screenWidth = getResources().getDisplayMetrics().widthPixels;
        int scrollWidth = clkView.getLeft() - (screenWidth / 2 - itemWidth / 2);
        rvView.scrollBy(scrollWidth, 0);
    }

移动到中间位置基本原理:先计算出屏幕宽度screenWidth,被点击View的宽度itemWidth,被点击View距离左边的距离为clkView.getLeft(),需要移动的宽度是 clkView.getLeft() - (screenWidth / 2 - itemWidth / 2);

这些距离计算,在纸上画一下就比较清晰了,我画了一下,有点难看,但是能说明问题,不清楚的多想想。
计算距离

完整示例代码如下:

package com.li.recyclerviewdemo;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import com.li.recyclerviewdemo.RvAdapter.OnItemClickListener;

import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {

    private RecyclerView rvView;
    private LinearLayoutManager layoutManager;
    private RvAdapter adapter;
    private List<TestBeans> beanList = new ArrayList<TestBeans>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getDatas();
        initView();
    }

    private void initView() {
        rvView = (RecyclerView) findViewById(R.id.rvView);
        layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        rvView.setLayoutManager(layoutManager);

        adapter = new RvAdapter(this, beanList);
        rvView.setAdapter(adapter);

        adapter.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                Toast.makeText(MainActivity.this, "-->" + position, Toast.LENGTH_SHORT).show();
                moveToMiddle(view);
                adapter.notifyDataSetChanged();
            }
        });
    }

    /**
     * 滚动到中间位置
     * @param clkView  被点击的View
     */
    public void moveToMiddle(View clkView){
        int itemWidth = clkView.getWidth();
        int screenWidth = getResources().getDisplayMetrics().widthPixels;
        int scrollWidth = clkView.getLeft() - (screenWidth / 2 - itemWidth / 2);
        rvView.scrollBy(scrollWidth, 0);
    }

    private void getDatas() {
        Calendar cal = Calendar.getInstance(Locale.CHINA);
        SimpleDateFormat sdfMd = new SimpleDateFormat("MM-dd");

        String[] dayNames = getResources().getStringArray(R.array.week_day);

        for (int i = 0; i < 15; i++) {
            cal.add(Calendar.DAY_OF_MONTH, 1);
            Date date = cal.getTime();
            String dateMd = sdfMd.format(date);

            int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK) - 1;
            if (dayOfWeek < 0) {
                dayOfWeek = 0;
            }
            String day = dayNames[dayOfWeek];

            TestBeans bean = new TestBeans();
            bean.setDateMd(dateMd);
            bean.setDateDay(day);
            bean.setPrice("¥" + (i+1) * 100); 

            beanList.add(bean);
        }
    }

}
posted on 2018-03-20 19:23  lishbo  阅读(644)  评论(0编辑  收藏  举报