RecyclerView+SearchView (简单实现)

RecyclerView+SearchView (简单实现)

简述: 简单实现点赞计数功能,按照个人想法实现文本检索功能,针对界面进行了美化。 (个人理解,有误指出)

检索功能实现思路:

控件导入:直接引入官方自带的SearchView控件,期间也是深受版本问题的困扰,如果导入控件使用androidx.appcompat.widget.SearchView报错,可以换成SearchView,(建议还是使用GUI界面拖动,版本问题是个诟病) 建议自己实现EditText。

简单思路:

(1)SearchView自带搜索图标和删除键,直接引入控件即可

(2) 实现搜索列表的即时显示,我们可以想一下,显示列表是根据数据创建一个adapter并设置显示,那么我们可以找到我们需要的数据,加入对应的List之中创建一个搜索结果的adapter,这样就能达到显示搜索结果的目的,即时性的实现采用监听器之中实现的onQueryTextChange方法,每搜索框改变一个字符便会回调该方法,每次调用该方法我们就创建一个新的adapter更新数据。

(3) 搜索文本匹配可以采用模拟匹配(小文本)或者 正则表达式匹配,但是两者的匹配标准不同(之后具体实现会提到) 。

(3) 每次找到对应的新数据之前先把原来储存用的LIst清空。

具体实现:

(1) 匹配所有的标签是否含有检索文本(搜索框的输入),我这里的子串的定义就是,按照先后顺序去掉若干个能得到目标串,这个串就称之为父串。比如:好久不见。 我们可以认定为是 “好不”的父串 ,简单来说,只要是按照顺序,能够找出每一个字符,我们就称之为父串。 实现方法:简单的正则表达式匹配 , 将输入的字符串拆分成单个字符 ,转化为正则表达式

诸如 : 字符1{1} + "[sS]" + 字符2{1} ,字符1{1} 代表字符1出现一次,"[sS]"代表匹配所有的字符(空或者非空)

这样的实现实际上就是为了贴合我们上面所说的子串理论,只要按照顺序出现一个字符1 。。。。。 字符2即可,中间出现的字符我们可以默认为任意,这样就可以用正则表达式完成文本匹配。

(2) 匹配的第二种实现,简单的模拟即可(实际上可以来个kmp),把搜索框的字符串进行拆分,去每一个标签之中寻找,每次都标记当前标签之中出现过的搜索框字符(bool数组标记即可),这样的匹配只要求出现过搜索框之中的所有字符就是合法的。 例子: 搜索框输入AS,对应的ASR在第一二种方法之中都会被匹配到 ,但是输入SA,只有第二种之中才会匹配到ASR。

不足 :按照个人理解实现的检索功能,效率过低,文本匹配的模式单一,而且无法实现光亮操作。

点赞计数实现

实现方法1. 采用图片切换的方法,首先获取一系列带数字的图片的id,设置一个计数器,然后将获取的id组成一个数组,针对对应计数器设置对应id的图片。

实现方法2. 相应的弄一个TextView,设置对应的监听器,点击一次计数器加一,设置的文本+1

(两种方法,方法二渲染时间少,占用空间少)


效果图:

(1) 正则表达式匹配 + 文本框进行更新计数

(2) 正则表达式匹配 + 图片切换计数

(3) 模拟匹配 + 图片切换计数

(4) 模拟匹配 + 文本框进行更新计数

框架图

采用的javaBean

package com.example.logindemo;

public class AlbumInfo {
    public String title;
    public String info;
    public int  imageId;
    public AlbumInfo(String title, String info, int imageId) {
        this.title = title;
        this.info = info;
        this.imageId = imageId;
    }
    public String getTitle() {
        return title;
    }
    public String getInfo() {
        return info;
    }
    public int  getImageId() {
        return imageId;
    }
}

Recycler_View.java (方法一,模拟实现)

package com.example.logindemo;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.OrientationHelper;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Recycler_View extends AppCompatActivity {

    private List<AlbumInfo> mData = new ArrayList<>();
    /// 储存原始的总数据
    private List<AlbumInfo> search_mData = new ArrayList<>();
    /// 搜索之后的更新数据
    private SearchView searchView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recycler_view);
        getData();// 获取数据
        searchView = findViewById(R.id.search) ;
        RecyclerView recycleView = (RecyclerView)findViewById(R.id.babyAlbumlist);
        // 获取组件
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        recycleView.setLayoutManager(layoutManager);
        // 设置线性布局
        AlbumAdapter adapter = new AlbumAdapter(mData);
        recycleView.setAdapter(adapter);

        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }
            @Override
            public boolean onQueryTextChange(String newText) {
                // 当搜索框内容变化 , 新的搜索数据清除,并更新
                search_mData.clear();
                find(newText);
                AlbumAdapter adapter = new AlbumAdapter(search_mData);
                /// 新的adapter进行数据更新
                recycleView.setAdapter(adapter);
                return false;
            }
        });
    }
    private boolean check(String a,String b)
    {
        int  vis[] = new int[1000];//标记位置
        /// a 搜索框字符串 b标签字符串
        for (int i=0;i<a.length();++i)
        {
            char x = a.charAt(i);
            boolean flag = false;
            for (int j=0;j<b.length();++j)
            {
                char y = b.charAt(j);
                // 如果在标签之中该字符出现过,直接标记
                if(vis[j]==0 && x==y)
                {
                    vis[j]=1;
                    flag = true;
                    break;
                }
            }
            /// 未找到未标记的,说明不是合法的匹配
            if (!flag) return false;
        }
        return true;
    }
    private void find(String x)
    {
        for (int i=0;i<mData.size();++i)
        {
             if (check(x,mData.get(i).title))
             {
                 search_mData.add(mData.get(i));
                 /// 找到的新的,作为更新
             }
        }
    }
    private void getData()
    {
        AlbumInfo albumInfo = new AlbumInfo("DX-巭 A","悬浮核心科技带来突破性操控体验,手柄前端释放,球路更开阔。动力流体六角框搭配百洛碳纤维中管,刚柔相济,攻守圆通,全面操控。更适合把握节奏的控制型选手。",R.drawable.i1);
        mData.add(albumInfo);
        AlbumInfo albumInfo2 = new AlbumInfo("TK-7U F","轻量+30lbs高磅,挥拍轻松更好上手,适合喜欢轻量打感的进攻型球友。",R.drawable.i2);
        mData.add(albumInfo2);
        AlbumInfo albumInfo3 = new AlbumInfo("BRS-11R D","经典手感的继承,菱形破风框的升华,再现速度与操控的优异平衡。",R.drawable.i3);
        mData.add(albumInfo3);
        AlbumInfo albumInfo4 = new AlbumInfo("DX-9X B","动力流体六角框结合轻量化硬中管,挥拍出球自如舒畅,打在悬浮核心科技(FREE CORE)手柄,带来突破性操控体验,更适合控制型打法的选手",R.drawable.i4);
        mData.add(albumInfo4);
        AlbumInfo albumInfo5 = new AlbumInfo("JS-12F J  ","JS-12的好拍档,外表清新,内在灵活,速攻致胜!具有轻快的手感及良好的舒适性,让你的击球瞬间更具有爆发力。",R.drawable.i5);
        mData.add(albumInfo5);
        AlbumInfo albumInfo6 = new AlbumInfo("ARS-70K F","新的回弹技术实现力量与速度并存的理想,挑战速度拍的新高度,适合节奏多变的双打选手及防守反击的单打选手。",R.drawable.i6);
        mData.add(albumInfo6);
        AlbumInfo albumInfo7 = new AlbumInfo("TK-F C A","小平头与72孔精确扎实的利爪设定,进阶导入PYROFIL及弹力盾科技,搭配锐白涂装,体现稳狠准的进攻美学。",R.drawable.i7);
        mData.add(albumInfo7);
        AlbumInfo albumInfo8 = new AlbumInfo("TK-F C LTD GB A","戴资颖签名球拍,印有戴爸亲笔提字『相信自己』刺青,代表性的小平头与72孔精确扎实设定,搭配FREE CORE悬浮核心科技人造柄,展现快狠准的进攻美学。戴资颖签名球拍,印有戴爸亲笔提字『相信自己』刺青,代表性的小平头与72孔精确扎实设定,搭配FREE CORE悬浮核心科技人造柄,展现快狠准的进攻美学。",R.drawable.i8);
        mData.add(albumInfo8);
        AlbumInfo albumInfo9 = new AlbumInfo("DX-8K F","全面偏进攻型球拍,搭载高韧动力纤维,可提高球拍的减震性能,击球时让手感更加扎实。",R.drawable.i9);
        mData.add(albumInfo9);
        AlbumInfo albumInfo10 = new AlbumInfo("TK-烎 F","易攻迅捷,拍拍精准,适合主动进击的球友使用。",R.drawable.i10);
        mData.add(albumInfo10);
        AlbumInfo albumInfo11 = new AlbumInfo("JS-2SP C","JS-12的中级拍,保留了强芯填充技术的稳定手感及球拍轻量化的特点,适合能轻松快速上手的羽球爱好者。",R.drawable.i11);
        mData.add(albumInfo11);
        AlbumInfo albumInfo12 = new AlbumInfo("DX-巭 A","悬浮核心科技带来突破性操控体验,手柄前端释放,球路更开阔。动力流体六角框搭配百洛碳纤维中管,刚柔相济,攻守圆通,全面操控。更适合把握节奏的控制型选手。",R.drawable.i1);
        mData.add(albumInfo12);
        AlbumInfo albumInfo13 = new AlbumInfo("TK-7U F","轻量+30lbs高磅,挥拍轻松更好上手,适合喜欢轻量打感的进攻型球友。",R.drawable.i2);
        mData.add(albumInfo13);
        AlbumInfo albumInfo14 = new AlbumInfo("BRS-11R D","经典手感的继承,菱形破风框的升华,再现速度与操控的优异平衡。",R.drawable.i3);
        mData.add(albumInfo14);
        AlbumInfo albumInfo15 = new AlbumInfo("DX-9X B","动力流体六角框结合轻量化硬中管,挥拍出球自如舒畅,打在悬浮核心科技(FREE CORE)手柄,带来突破性操控体验,更适合控制型打法的选手",R.drawable.i4);
        mData.add(albumInfo15);
        AlbumInfo albumInfo16 = new AlbumInfo("JS-12F J  ","JS-12的好拍档,外表清新,内在灵活,速攻致胜!具有轻快的手感及良好的舒适性,让你的击球瞬间更具有爆发力。",R.drawable.i5);
        mData.add(albumInfo16);
        AlbumInfo albumInfo17 = new AlbumInfo("ARS-70K F","新的回弹技术实现力量与速度并存的理想,挑战速度拍的新高度,适合节奏多变的双打选手及防守反击的单打选手。",R.drawable.i6);
        mData.add(albumInfo17);
        AlbumInfo albumInfo18 = new AlbumInfo("TK-F C A","小平头与72孔精确扎实的利爪设定,进阶导入PYROFIL及弹力盾科技,搭配锐白涂装,体现稳狠准的进攻美学。",R.drawable.i7);
        mData.add(albumInfo18);
        AlbumInfo albumInfo19 = new AlbumInfo("TK-F C LTD GB A","戴资颖签名球拍,印有戴爸亲笔提字『相信自己』刺青,代表性的小平头与72孔精确扎实设定,搭配FREE CORE悬浮核心科技人造柄,展现快狠准的进攻美学。戴资颖签名球拍,印有戴爸亲笔提字『相信自己』刺青,代表性的小平头与72孔精确扎实设定,搭配FREE CORE悬浮核心科技人造柄,展现快狠准的进攻美学。",R.drawable.i8);
        mData.add(albumInfo19);
        AlbumInfo albumInfo20 = new AlbumInfo("DX-8K F","全面偏进攻型球拍,搭载高韧动力纤维,可提高球拍的减震性能,击球时让手感更加扎实。",R.drawable.i9);
        mData.add(albumInfo20);
        AlbumInfo albumInfo21 = new AlbumInfo("TK-烎 F","易攻迅捷,拍拍精准,适合主动进击的球友使用。",R.drawable.i10);
        mData.add(albumInfo21);
        AlbumInfo albumInfo22 = new AlbumInfo("JS-2SP C","JS-12的中级拍,保留了强芯填充技术的稳定手感及球拍轻量化的特点,适合能轻松快速上手的羽球爱好者。",R.drawable.i11);
        mData.add(albumInfo22);
    }

}

Recycler_View.java (方法二,正则表达式实现)

private boolean check(String a,String b) {
        /// 这个是唯一要改的方法
        String regEx = new StringBuilder().append("").toString();
        /// 将搜索框的字符按照 字符1{1}[\s\S]*字符2{1}[\s\S]*字符3{1}..... 进行连接
        int l = a.length();
        for (int i=0;i<l;++i)
        {
            if (i==0)
            {
                regEx += a.charAt(i)+"{1}";
                continue;
            }
            regEx += "[\s\S]*"+a.charAt(i)+"{1}";
        }
//        System.out.println(regEx);
        Pattern p;
        Matcher m;
        p = Pattern.compile(regEx);
        System.out.println(p);
        m = p.matcher(b);
        System.out.println(m);
        /// 执行正则化  部分匹配
        if (m.find()) {
            return true;
        } else {
            return false;
        }
    }

AlbumAdapter.java (计数采用TextView)

package com.example.logindemo;
import android.content.Context;
import android.content.DialogInterface;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.recyclerview.widget.RecyclerView;

import java.util.List;

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

    private List<AlbumInfo> albumInfoList;
    private int cnt[] = new int[100];
    int pic[] = new int[]{R.drawable.text0,R.drawable.text1, R.drawable.text2, R.drawable.text3};
    static class ViewHolder extends RecyclerView.ViewHolder{
        ImageView album_thumb;
        TextView album_title;
        TextView album_info;
        TextView album_btn;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            this.album_thumb = (ImageView)itemView.findViewById(R.id.album_thumb);
            this.album_title = (TextView)itemView.findViewById(R.id.album_title);
            this.album_info =  (TextView)itemView.findViewById(R.id.album_info);
            this.album_btn =  (TextView) itemView.findViewById(R.id.btn);
            /// 获取id
        }
    }

    public AlbumAdapter(List<AlbumInfo> albumInfoList) {
        this.albumInfoList = albumInfoList;
        /// 构造函数
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        AlbumInfo album = albumInfoList.get(position);
        holder.album_thumb.setImageResource(album.getImageId());
        holder.album_title.setText(album.getTitle());
        holder.album_info.setText(album.getInfo());
        /// 数据填充
        Log.e("AlbumAdapter","onBindViewHolder"+position);
    }



    @Override
    public int getItemCount() {
        return albumInfoList.size();
    }
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview_bt,parent,false);
        final ViewHolder holder = new ViewHolder(view);
        Log.e("AlbumAdapter","onCreateViewHolder");
        /// 设置监听
        holder.album_thumb.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                int position = holder.getAdapterPosition();
                AlbumInfo data = albumInfoList.get(position);
                Toast.makeText(v.getContext(),data.getTitle()+"image",Toast.LENGTH_SHORT).show();
            }
        });
        holder.album_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v)
            {
                int position = holder.getAdapterPosition();
                showInfo(position,v.getContext());
                /// 对应位置的计数器加一
                cnt[position] += 1;
                /// 对应的text数值设置为+1
                holder.album_btn.setText(cnt[position]+"");

            }
        });
        return holder;
    }
    private void showInfo(int position, Context context)
    {
        AlbumInfo data = albumInfoList.get(position);
        new AlertDialog.Builder(context)
                .setTitle(data.getTitle())
                .setMessage(data.getInfo())
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                    }
                }).show();
    }
}

activity_recycler_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <androidx.appcompat.widget.SearchView
        android:id="@+id/search"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:iconifiedByDefault="true"
        android:background="@drawable/round_shape"
        android:queryHint="请输入搜索内容" />
        
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/babyAlbumlist"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

card_view_bt.xml (此时计数采用TextView显示)

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp"
    app:cardCornerRadius="5dp"
    app:cardElevation="2dp">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:background="@drawable/round_shape"
        android:padding="5dp">

        <ImageView
            android:id="@+id/album_thumb"
            android:layout_width="0dp"
            android:layout_height="137dp"
            android:layout_margin="5dp"
            android:layout_weight="1" />

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            android:orientation="vertical">

            <TextView
                android:id="@+id/album_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="16sp" />

            <TextView
                android:id="@+id/album_info"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textSize="14sp" />

            <TextView
                android:id="@+id/btn"
                android:layout_width="106dp"
                android:layout_height="104dp"
                android:layout_gravity="end"
                android:layout_marginEnd="10dp"
                android:layout_marginBottom="5dp"
                android:gravity="center"
                android:text="0"
                android:textSize="40sp" />
        </LinearLayout>

    </LinearLayout>
</androidx.cardview.widget.CardView>

card_view_bt.xml (此时计数采用ImageButton显示)

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp"
    app:cardCornerRadius="5dp"
    app:cardElevation="2dp">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:background="@drawable/round_shape"
        android:padding="5dp">

        <ImageView
            android:id="@+id/album_thumb"
            android:layout_width="0dp"
            android:layout_height="137dp"
            android:layout_margin="5dp"
            android:layout_weight="1" />

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            android:orientation="vertical">

            <TextView
                android:id="@+id/album_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="16sp" />

            <TextView
                android:id="@+id/album_info"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textSize="14sp" />

            <ImageButton
                android:id="@+id/album_btn"
                android:layout_width="61dp"
                android:layout_height="104dp"
                android:layout_gravity="end"
                android:layout_marginEnd="10dp"
                android:layout_marginBottom="5dp"
                android:background="@android:color/transparent"
                android:src="@drawable/text0" />
        </LinearLayout>
    </LinearLayout>
</androidx.cardview.widget.CardView>

齐芒行,川锋明!
原文地址:https://www.cnblogs.com/qimang-311/p/15505447.html