Android笔记(六):RecyclerView实现上/下滑隐藏/显示顶部搜索栏(item可点击)

效果如下:


主界面界面布局:

<?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"
    android:orientation="vertical"
    android:background="#fff"
    tools:context="com.example.mingnews.MainActivity">
    <LinearLayout
        android:id="@+id/search_bar"
        android:background="#345"
        android:paddingTop="30dp"
        android:paddingBottom="5dp"
        android:paddingStart="5dp"
        android:paddingEnd="5dp"
        android:layout_width="match_parent"
        android:layout_height="85dp"
        android:focusable="true"
        android:focusableInTouchMode="true">
        <EditText
            android:id="@+id/exit_text"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:textColor="@android:color/white"
            android:textColorHint="@android:color/white"
            android:hint="@string/query_hint"/>

        <ImageView
            android:id="@+id/query_button"
            android:layout_width="35dp"
            android:layout_height="35dp"
            android:paddingTop="5dp"
            android:clickable="true"
            android:focusable="true"
            android:src="@drawable/search_tubiao" />
    </LinearLayout>

    <com.example.mingnews.MingRecyclerView
        android:id="@+id/list_view"
        android:layout_below="@id/search_bar"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>
主要是一个顶部的搜索栏加一个自定义的recyclerview。
其中将edittext控件的父布局的focusable和focusableInTouchMode属性设置为true可避免一显示该界面就自动弹出输入法。

自定义recyclerview:

public class MingRecyclerView extends RecyclerView {
    private int mFirstY;
    public MingRecyclerView(Context context) {
        super(context);
    }

    public MingRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MingRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        if(e.getAction()==MotionEvent.ACTION_DOWN)mFirstY= (int) e.getY();
        return super.onInterceptTouchEvent(e);
    }

    @Override
    public boolean performClick() {
        return super.performClick();
    }

    public int getTouchPointY() {
        return mFirstY;
    }
}
关键点是onInterceptTouchEvent方法,用于获取手指接触屏幕时触摸点的y轴坐标。

由于实现了OnTouchListener监听,所以复写performClick方法以消除警告。

主界面:

public class MainActivity extends Activity {
    private View searchBar;
    private EditText editText;
    private ImageView queryButton;
    private MingRecyclerView recyclerView;
    private List<MainItemBean> data;
    int mFirstY, mCurrentY, marginTop;
    boolean direction;

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

        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

        data = new ArrayList<>();
        data.add(new MainItemBean(R.drawable.ic_launcher_background, "头条"));
        data.add(new MainItemBean(R.drawable.ic_launcher_background, "社会"));
        data.add(new MainItemBean(R.drawable.ic_launcher_background, "国内"));
        data.add(new MainItemBean(R.drawable.ic_launcher_background, "国际"));
        data.add(new MainItemBean(R.drawable.ic_launcher_background, "娱乐"));
        data.add(new MainItemBean(R.drawable.ic_launcher_background, "体育"));
        data.add(new MainItemBean(R.drawable.ic_launcher_background, "军事"));
        data.add(new MainItemBean(R.drawable.ic_launcher_background, "科技"));
        data.add(new MainItemBean(R.drawable.ic_launcher_background, "财经"));
        data.add(new MainItemBean(R.drawable.ic_launcher_background, "时尚"));

        initView();
    }

    private void initView() {
        marginTop = DisplayUtil.dp2px(this, 85); //顶部搜索栏高度为85dp,转为像素值255
        MainListAdapter adapter = new MainListAdapter(this, data);
        adapter.setOnItemClickListener(new MainListAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                Toast.makeText(MainActivity.this, data.get(position).getTitle(), Toast.LENGTH_SHORT).show();
            }
        });
        searchBar = findViewById(R.id.search_bar);
        editText=findViewById(R.id.exit_text);
        queryButton=findViewById(R.id.query_button);
        queryButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String query=editText.getText().toString();

            }
        });

        recyclerView = findViewById(R.id.list_view);
        recyclerView.setLayoutManager(new LinearLayoutManager(this, OrientationHelper.VERTICAL, false));
        recyclerView.setAdapter(adapter);


        recyclerView.setOnTouchListener(new View.OnTouchListener() {
            @SuppressLint("ClickableViewAccessibility")
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {

                switch (motionEvent.getAction()) {
                    case MotionEvent.ACTION_MOVE:
                        mFirstY=recyclerView.getTouchPointY();
                        mCurrentY = (int) motionEvent.getY();
                        Log.d("ttt","mFirstY:"+mFirstY+" mCurrentY:"+mCurrentY);
                        RelativeLayout.LayoutParams top = (RelativeLayout.LayoutParams) searchBar.getLayoutParams();
                        if (mCurrentY - mFirstY > 0) {
                            direction = false; //向下滑动
                        } else {
                            direction = true; //向上滑动
                        }
                        Log.d("uuu","top.margin:"+top.topMargin+" direction:"+direction);
                        if (direction) {
                            Log.d("uuu","上滑");
                            if (top.topMargin > -marginTop) {
                                top.topMargin += mCurrentY - mFirstY;
                                if(top.topMargin<-marginTop)
                                    top.topMargin=-marginTop;
                                Log.d("uuu","top2:"+top.topMargin);
                                searchBar.requestLayout();
                            }
                        } else {
                            if (top.topMargin < 0) {
                                top.topMargin += mCurrentY - mFirstY;
                                if(top.topMargin>0)top.topMargin=0;
                                searchBar.requestLayout();
                            }
                        }
                        break;
                }
                return false;
            }
        });
    }
}
关键点是OnTouchListener监听,手指滑动时判断是上滑还是下滑,然后用滑动的距离(mCurrentY-mFirstY)来设置顶部搜索栏的topMargin(顶部留白,这里值不大于0),调用requestLayout重新布局。

注:(试验发现)由于recyclerview实现item点击监听,会导致onTouch方法接收不到ACTION_DOWN事件,这是为什么要通过复写onInterceptTouchEvent方法来获取ACTION_DOWN事件。而recyclerview取消任何item点击监听的情况下,onTouch方法偶尔能接收到ACTION_DOWN事件,具体原因未深究,如有人知道请告诉我,谢谢!

附上适配器和item布局文件:

public class MainListAdapter extends RecyclerView.Adapter {
    private Context context;
    private List<MainItemBean> data;
    private OnItemClickListener itemClickListener;
    public MainListAdapter(Context context, List data){
        this.context=context;
        this.data=data;
    }
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view= LayoutInflater.from(context).inflate(R.layout.main_list_item,parent,false);
        return new MyViewHolder(view,itemClickListener);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ImageView imageView=((MyViewHolder)holder).v.findViewById(R.id.background);
        imageView.setImageResource(data.get(position).getImageId());
        TextView textView=((MyViewHolder)holder).v.findViewById(R.id.item_title);
        textView.setText(data.get(position).getTitle());
    }

    @Override
    public int getItemCount() {
        return data.size();
    }
    class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
        private OnItemClickListener onItemClickListener;
        private View v;
        public MyViewHolder(View itemView,OnItemClickListener onItemClickListener) {
            super(itemView);
            this.onItemClickListener=onItemClickListener;
            itemView.setOnClickListener(this);
            v=itemView;
        }

        @Override
        public void onClick(View view) {
            if(onItemClickListener!=null)
                onItemClickListener.onItemClick(v,getAdapterPosition());
        }
    }

    public interface OnItemClickListener{
        void onItemClick(View view,int position);
    }
    public void setOnItemClickListener(OnItemClickListener onItemClickListener){
        this.itemClickListener=onItemClickListener;
    }
}

<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="105dp"
    android:padding="15dp">
    <ImageView
        android:id="@+id/background"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:background="#678"/>

    <TextView
        android:id="@+id/item_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_centerVertical="true"
        android:layout_marginEnd="47dp"
        android:textSize="35sp"
        tools:text="科技" />
</RelativeLayout>


猜你喜欢

转载自blog.csdn.net/weixin_40855673/article/details/79101407