1. 程式人生 > >Android仿微信搜尋,Recyclerview+關鍵字動態匹配篩選變色效果(Edittext+Recyclerview)

Android仿微信搜尋,Recyclerview+關鍵字動態匹配篩選變色效果(Edittext+Recyclerview)

一、概述

  我們要實現的是模仿微信的搜尋效果,通過監聽Edittext中文字的變化動態匹配Recyclerview列表中文字,重新整理列表,並將關鍵字變色顯示。
  首先上圖,展示我們將要實現的效果(關鍵字是有顏色變化的,列表也有重新整理。我們的gif圖表現的不是很明顯)。
1. 關鍵字全部變色效果
  然後是部分匹配——>即例如我們資料“第一天第一天”,只有第一個“一”變色。我本意是要寫上邊那個全部變色的效果的,偶然發現了只能匹配部分的問題,所以拿出來問題與解決方法與大家分享下。
2. 部分匹配效果

二、實現

  所有程式碼已上傳,並且有詳細的註釋,連結地址在文末。大家稍後可以下載。
1. 首先上item

佈局檔案:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:id="@+id/ll_item"
    android:layout_marginTop
="3dp" android:background="@drawable/shape_search" android:layout_marginRight="8dp" android:layout_marginLeft="8dp" android:layout_height="60dp">
<com.facebook.drawee.view.SimpleDraweeView android:id="@+id/imgv_simple" android:layout_marginRight="5dp" android:layout_marginLeft
="10dp" android:layout_gravity="center" fresco:backgroundImage="@mipmap/imgv_girl" fresco:placeholderImage="@mipmap/imgv_girl" fresco:roundBottomLeft="false" fresco:roundBottomRight="true" fresco:roundTopLeft="true" fresco:roundTopRight="false" fresco:roundedCornerRadius="50dp" android:layout_width="45dp" android:layout_height="45dp" />
<TextView android:textColor="#7f44ff" android:gravity="center" android:text="123" android:id="@+id/tv_text" android:marqueeRepeatLimit="marquee_forever" android:ellipsize="marquee" android:focusable="true" android:singleLine="true" android:layout_gravity="center" android:layout_width="match_parent" android:layout_height="45dp" /> </LinearLayout>

  利用Fresco的圓角效果實現我們item中圖片的葉子形(姑且叫它葉子形吧)樣式,並且給整個LinearLayout佈局加一個5dp圓角並且帶黑色邊框的background,如此便形成了我們效果圖中每個item的效果。
2. 列表頁佈局檔案:

<?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"
    android:background="#f5f2f2"
    tools:context="com.example.txs.myapplication.MainActivityWhole">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:background="#6CC4B8"
        android:gravity="center"
        android:text="搜尋匹配關鍵字(全部變色)"
        android:textColor="#fff" />
        <LinearLayout
            android:focusable="true"
            android:focusableInTouchMode="true"
            android:layout_marginTop="5dp"
            android:layout_width="match_parent"
            android:layout_height="35dp"
            android:layout_gravity="center"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:background="@drawable/shape_search"
            android:orientation="horizontal">
            <ImageView
                android:layout_marginLeft="3dp"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:layout_gravity="center"
                android:scaleType="centerInside"
                android:src="@mipmap/imgv_search" />
            <EditText
                android:id="@+id/edt_search"
                android:layout_width="0dp"
                android:layout_height="28dp"
                android:layout_gravity="center"
                android:layout_weight="1"
                android:background="@null"
                android:imeOptions="actionSearch"
                android:lines="1"
                android:singleLine="true" />
            <ImageView
                android:layout_marginRight="3dp"
                android:id="@+id/imgv_delete"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:layout_gravity="center"
                android:scaleType="centerInside"
                android:src="@mipmap/imgv_delete"
                android:visibility="gone" />
        </LinearLayout>
    <android.support.v7.widget.RecyclerView
        android:id="@+id/rc_search"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

  整個頁面很簡單,由上到下是title,搜尋框,Recyclerview。我們的重點不在這裡,所以介面搭建的不是很複雜,能看就好~接下來才是我們的重點。
3. 介面卡①—>部分匹配的介面卡:

/**
 * @author txs
 * @date 2018/01/16
 */

public class RcAdapterPartChange extends RecyclerView.Adapter<RcAdapterPartChange.MyViewHolder> {
    private Context context;
    /**
     * adapter傳遞過來的資料集合
     */
    private List<String> list = new ArrayList<>();
    /**
     * 變色資料的其實位置 position
     */
    private int beginChangePos;
    /**
     * 需要改變顏色的text
     */
    private String text;
    /**
     * text改變的顏色
     */
    private ForegroundColorSpan span;

    /**
     * 在MainActivity中設定text和span
     */
    public void setText(String text, ForegroundColorSpan span) {
        this.text = text;
        this.span = span;
    }

    public RcAdapterPartChange(Context context, List<String> list) {
        this.context = context;
        this.list = list;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        MyViewHolder holder = new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.item_search, parent, false));
        return holder;
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, final int position) {
        /**如果沒有進行搜尋操作或者搜尋之後點選了刪除按鈕 我們會在MainActivity中把text置空並傳遞過來*/
        if (text != null) {
            //獲取匹配文字的 position
            beginChangePos = list.get(position).indexOf(text);
            // 文字的builder 用來做變色操作
            SpannableStringBuilder builder = new SpannableStringBuilder(list.get(position));
            //如果沒有匹配到關鍵字的話 list.get(position).indexOf(text)會返回-1
            if (beginChangePos != -1) {
                //設定呈現的文字
                builder.setSpan(span, beginChangePos, beginChangePos + text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                holder.mTvText.setText(builder);
            }
        } else {
            holder.mTvText.setText(list.get(position));
        }
        //點選監聽
        holder.mLlItem.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                onItemClickListener.onClick(view, position);
            }
        });
    }

    @Override
    public int getItemCount() {
        return list.size();
    }

    public interface onItemClickListener {
        void onClick(View view, int pos);
    }

    /**
     * Recyclerview的點選監聽介面
     */
    private onItemClickListener onItemClickListener;

    public void setOnItemClickListener(RcAdapterPartChange.onItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    class MyViewHolder extends RecyclerView.ViewHolder {
        private LinearLayout mLlItem;
        private SimpleDraweeView mImgvSimple;
        private TextView mTvText;

        public MyViewHolder(View itemView) {
            super(itemView);
            mLlItem = (LinearLayout) itemView.findViewById(R.id.ll_item);
            mImgvSimple = (SimpleDraweeView) itemView.findViewById(R.id.imgv_simple);
            mTvText = (TextView) itemView.findViewById(R.id.tv_text);
        }
    }
}

  先說說這個介面卡的瑕疵,由於.indexOf()的坑,使用這個介面卡產生的最終效果如我們的第二張圖,只能匹配每個item第一條關鍵字,即比如我們的資料“第一天一天”,它只能使第一個”一”字變色(當然整個列表的重新整理和匹配效果是沒問題的,它隻影響了關鍵字的變色效果。僅此而已!!)。而且不論我們後續還有多少個“一”,它依舊只能變色第一個“一”字。有的人可能碰巧會需要這個效果,所以我放上來程式碼和解決思路供大家參考。
首先我們介面卡在建立時傳過來一個list集合,集合裡面可以包含你從網路或者資料庫或者其他方式獲取到的資料(已經經過篩選,比如我們搜尋“一”字,傳過來的集合是那些包含“一”字的資料)。然後提供一個set方法void setText(String text, ForegroundColorSpan span),在重新整理介面卡之前用setText()將我們的關鍵字以及關鍵字要變成的顏色傳過來,像這樣:

           //設定要變色的關鍵字
            adapter.setText(text, redSpan);
           //重新整理介面卡
            refreshUI();

然後介面卡就會重新執行到onBindViewHolder方法,重新整理介面,就可以看到我們的篩選和變色效果了。下面我們來分析這段程式碼:

 /**如果沒有進行搜尋操作或者搜尋之後點選了刪除按鈕 我們會在MainActivity中把text置空並傳遞過來*/
        if (text != null) {
            //獲取匹配文字的 position
            beginChangePos = list.get(position).indexOf(text);
            // 文字的builder 用來做變色操作
            SpannableStringBuilder builder = new SpannableStringBuilder(list.get(position));
            //如果沒有匹配到關鍵字的話 list.get(position).indexOf(text)會返回-1
            if (beginChangePos != -1) {
                //設定呈現的文字
                builder.setSpan(span, beginChangePos, beginChangePos + text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                holder.mTvText.setText(builder);
            }
        } else {
            holder.mTvText.setText(list.get(position));
        }

  開始我們有一個對text判空的操作,在後面的Activity程式碼中你可以看到,我在重新整理介面卡之前,先判斷edittext中是否輸入了關鍵字,如果有關鍵字則會通過setText(text,span)把關鍵字傳遞過來,如果沒有關鍵字則會置空setText(null,null)。如果有關鍵字的話,我們用indexOf()找到它的起始位置(position),當然如果沒有匹配到關鍵字的話list.get(position).indexOf(text)會返回-1,然後我們會通過SpannableStringBuilder對關鍵字進行變色操作。下面我們再來驗證一些indexOf()的問題,上程式碼:

 public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button mBtnIndexof;
    private Button mBtnMatcher;
    private String mString;
    private String mKeyword;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBtnIndexof = (Button) findViewById(R.id.btn_indexof);
        mBtnMatcher = (Button) findViewById(R.id.btn_matcher);
        mString = "第一天第一夜第一個時辰";
        mKeyword = "一";
        setListener();
    }
    private void setListener() {
        mBtnIndexof.setOnClickListener(this);
        mBtnMatcher.setOnClickListener(this);
    }
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_indexof:
               int pos = mString.indexOf(mKeyword);
                Log.e("test", "indexof== "+pos);
                break;
            case R.id.btn_matcher:
                //條件 keyword
                Pattern pattern = Pattern.compile(mKeyword);
                //匹配
                Matcher matcher = pattern.matcher(mString);
                while (matcher.find()) {
                    int start = matcher.start();
                    Log.e("test", "macher== "+start);
                    int end = matcher.end();
                }
                break;
            default:
                break;
        }
    }
}

結果:

01-16 22:23:06.831 1581-1581/com.example.testinndexof E/test: indexof== 1
01-16 22:23:10.139 1581-1581/com.example.testinndexof E/test: macher== 1
01-16 22:23:10.139 1581-1581/com.example.testinndexof E/test: macher== 4
01-16 22:23:10.139 1581-1581/com.example.testinndexof E/test: macher== 7

  通過控制檯輸出的結果我們可以看到,indexOf()只匹配到了第一個“一”的位置,之後沒有繼續匹配。這也是indexOf()的原理所致。所以用此方法只能匹配到首個對應字元的問題已經找到了,接下來應該怎麼做讓它完全匹配呢?上述程式碼已經給出瞭解決方法,用Matchermatcher.find()
4. 介面卡②—>全部匹配的介面卡:

/**
 * @author txs
 * @date 2018/01/16
 */

public class RcAdapterWholeChange extends RecyclerView.Adapter<RcAdapterWholeChange.MyViewHolder> {
    private Context context;
    /**
     * adapter傳遞過來的資料集合
     */
    private List<String> list = new ArrayList<>();
    /**
     * 需要改變顏色的text
     */
    private String text;

    /**
     * 在MainActivity中設定text
     */
    public void setText(String text) {
        this.text = text;
    }

    public RcAdapterWholeChange(Context context, List<String> list) {
        this.context = context;
        this.list = list;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        MyViewHolder holder = new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.item_search, parent, false));
        return holder;
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, final int position) {
        /**如果沒有進行搜尋操作或者搜尋之後點選了刪除按鈕 我們會在MainActivity中把text置空並傳遞過來*/
        if (text != null) {
            //設定span
            SpannableString string = matcherSearchText(Color.rgb(255, 0, 0), list.get(position), text);
            holder.mTvText.setText(string);
        } else {
            holder.mTvText.setText(list.get(position));
        }
        //點選監聽
        holder.mLlItem.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                onItemClickListener.onClick(view, position);
            }
        });
    }

    @Override
    public int getItemCount() {
        return list.size();
    }

    /**
     * Recyclerview的點選監聽介面
     */
    public interface onItemClickListener {
        void onClick(View view, int pos);
    }

    private onItemClickListener onItemClickListener;

    public void setOnItemClickListener(RcAdapterWholeChange.onItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    class MyViewHolder extends RecyclerView.ViewHolder {
        private LinearLayout mLlItem;
        private SimpleDraweeView mImgvSimple;
        private TextView mTvText;

        public MyViewHolder(View itemView) {
            super(itemView);
            mLlItem = (LinearLayout) itemView.findViewById(R.id.ll_item);
            mImgvSimple = (SimpleDraweeView) itemView.findViewById(R.id.imgv_simple);
            mTvText = (TextView) itemView.findViewById(R.id.tv_text);
        }
    }

    /**
     * 正則匹配 返回值是一個SpannableString 即經過變色處理的資料
     */
    private SpannableString matcherSearchText(int color, String text, String keyword) {
        SpannableString spannableString = new SpannableString(text);
        //條件 keyword
        Pattern pattern = Pattern.compile(keyword);
        //匹配
        Matcher matcher = pattern.matcher(spannableString);
        while (matcher.find()) {
            int start = matcher.start();
            int end = matcher.end();
            //ForegroundColorSpan 需要new 不然也只能是部分變色
            spannableString.setSpan(new ForegroundColorSpan(color), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        //返回變色處理的結果
        return spannableString;
    }

}

  改動不大,重點是一個matcherSearchText方法,返回值是SpannableString,也就是經過我們經過變色處理的文字。主要使用matcher.find()方法找到所以有匹配的關鍵字,它的效果已經在上邊的程式碼中展示過了(請看上邊的控制檯輸出結果)。
5. Activity中的程式碼:

public class MainActivityWhole extends AppCompatActivity {
    /**
     * 搜尋框
     */
    private EditText mEdtSearch;
    /**
     * 刪除按鈕
     */
    private ImageView mImgvDelete;
    /**
     * recyclerview
     */
    private RecyclerView mRcSearch;
    /**
     * 全部匹配的介面卡
     */
    private RcAdapterWholeChange adapter;
    /**
     * 所有資料 可以是聯網獲取 如果有需要可以將其儲存在資料庫中 我們用簡單的String做演示
     */
    private List<String> wholeList;
    /**
     * 此list用來儲存符合我們規則的資料
     */
    private List<String> list;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_whole);
        initView();
        initData();
        refreshUI();
        setListener();
    }

    /**
     * 設定監聽
     */
    private void setListener() {
        //edittext的監聽
        mEdtSearch.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            //每次edittext內容改變時執行 控制刪除按鈕的顯示隱藏
            @Override
            public void afterTextChanged(Editable editable) {
                if (editable.length() == 0) {
                    mImgvDelete.setVisibility(View.GONE);
                } else {
                    mImgvDelete.setVisibility(View.VISIBLE);
                }
                //匹配文字 變色
                doChangeColor(editable.toString().trim());
            }
        });
        //recyclerview的點選監聽
        adapter.setOnItemClickListener(new RcAdapterWholeChange.onItemClickListener() {
            @Override
            public void onClick(View view, int pos) {
                Toast.makeText(MainActivityWhole.this, "妹子 pos== " + pos, Toast.LENGTH_SHORT).show();
            }
        });
        //刪除按鈕的監聽
        mImgvDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mEdtSearch.setText("");
            }
        });
    }

    /**
     * 字型匹配方法
     */
    private void doChangeColor(String text) {
        //clear是必須的 不然只要改變edittext資料,list會一直add資料進來
        list.clear();
        //不需要匹配 把所有資料都傳進來 不需要變色
        if (text.equals("")) {
            list.addAll(wholeList);
            //防止匹配過文字之後點選刪除按鈕 字型仍然變色的問題
            adapter.setText(null);
            refreshUI();
        } else {
            //如果edittext裡面有資料 則根據edittext裡面的資料進行匹配 用contains判斷是否包含該條資料 包含的話則加入到list中
            for (String i : wholeList) {
                if (i.contains(text)) {
                    list.add(i);
                }
            }
            //設定要變色的關鍵字
            adapter.setText(text);
            refreshUI();
        }
    }

    private void initData() {
        //假資料  實際開發中請從網路或者資料庫獲取
        wholeList = new ArrayList<>();
        list = new ArrayList<>();
        wholeList.add("第一天一天");
        wholeList.add("第二天一天");
        wholeList.add("第三天一天");
        wholeList.add("第四天一天");
        wholeList.add("第五天五天");
        wholeList.add("第六天一天");
        wholeList.add("第七天七天");
        wholeList.add("第一天八天");
        wholeList.add("第一天九天");
        wholeList.add("第一天十天");
        wholeList.add("第一天十一天");
        //初次進入程式時 展示全部資料
        list.addAll(wholeList);
    }

    /**
     * 重新整理UI
     */
    private void refreshUI() {
        if (adapter == null) {
            adapter = new RcAdapterWholeChange(this, list);
            mRcSearch.setAdapter(adapter);
        } else {
            adapter.notifyDataSetChanged();
        }
    }

    private void initView() {
        mEdtSearch = (EditText) findViewById(R.id.edt_search);
        mImgvDelete = (ImageView) findViewById(R.id.imgv_delete);
        mRcSearch = (RecyclerView) findViewById(R.id.rc_search);
        //Recyclerview的配置
        mRcSearch.setLayoutManager(new LinearLayoutManager(this));
    }
}

  這裡我們的思路是首先定義兩個集合(wholeListlist),wholeList用來儲存我們獲取的全部資料,list用來儲存我們經過篩選後的資料。在為進行搜尋操作是預設展示所有資料,所以會有list.addAll(wholeList)。之後通過對Edittext的變化監聽afterTextChanged,在裡面執行刪除按鈕的顯示隱藏以及匹配文字並變色的doChangeColor()方法。

 //每次edittext內容改變時執行 控制刪除按鈕的顯示隱藏
            @Override
            public void afterTextChanged(Editable editable) {
                if (editable.length() == 0) {
                    mImgvDelete.setVisibility(View.GONE);
                } else {
                    mImgvDelete.setVisibility(View.VISIBLE);
                }
                //匹配文字 變色
                doChangeColor(editable.toString().trim());
            }

  接下來我們要講的是doChangeColor()這個方法,首先看程式碼:

/**
     * 字型匹配方法
     */
    private void doChangeColor(String text) {
        //clear是必須的 不然只要改變edittext資料,list會一直add資料進來
        list.clear();
        //不需要匹配 把所有資料都傳進來 不需要變色
        if (text.equals("")) {
            list.addAll(wholeList);
            //防止匹配過文字之後點選刪除按鈕 字型仍然變色的問題
            adapter.setText(null);
            refreshUI();
        } else {
            //如果edittext裡面有資料 則根據edittext裡面的資料進行匹配 用contains判斷是否包含該條資料 包含的話則加入到list中
            for (String i : wholeList) {
                if (i.contains(text)) {
                    list.add(i);
                }
            }
            //設定要變色的關鍵字
            adapter.setText(text);
            refreshUI();
        }
    }

  在執行doChangeColor()之初,我們要清空一下list,不然如果你第一次搜尋了“一”,第二次搜尋了“二”,那麼最終的展示效果會是包含了“一”和“二”資料的並集~,接下來我們會判斷Edittext裡面是否有關鍵字(搜尋條件),如果沒有關鍵字,即進行展示全部資料並且不變色的操作

            list.addAll(wholeList);
            //防止匹配過文字之後點選刪除按鈕 字型仍然變色的問題
            adapter.setText(null);

如果有關鍵字,則對wholeList進行遍歷,匹配。把符合條件(i.contains(text))的資料加入到list集合中並進行展示。

三、後記

  整個專案並不難,而且程式碼中都有詳細的註釋。但是例如SpannableString的玩法以及PatternMatcher的使用沒有展開來講。最近我在考慮寫一些合集來把一些基礎知識總結一下放上來,這樣以後在寫文章的時候可以這樣寫:

重點是一個matcherSearchText方法,返回值是SpannableStringSpannableString怎麼用?請見我的文章《Android 之SpannableString用法詳解》。

相關推薦

Android仿搜尋Recyclerview+關鍵字動態匹配篩選變色效果Edittext+Recyclerview

一、概述   我們要實現的是模仿微信的搜尋效果,通過監聽Edittext中文字的變化動態匹配Recyclerview列表中文字,重新整理列表,並將關鍵字變色顯示。   首先上圖,展示我們將要實現的效果(關鍵字是有顏色變化的,列表也有重新整理。我們的gif圖

Android 仿調用第三方應用導航(百度高德、騰訊)

detail decorview fcm onclick api 描述 log def repr 實現目標 先來一張微信功能截圖看看要做什麽 其實就是有一個目的地,點擊目的地的時候彈出可選擇的應用進行導航。 大腦動一下,要實現這個功能應該大體分成兩步: 底部彈出可選的地

android仿、QQ等聊天介面實現點選輸入框彈出軟鍵盤、點選其他區域收起軟鍵盤預設滑動至最低端

如圖所示,點選輸入框及選擇圖片和傳送按鈕時軟鍵盤顯示且不消失,點選其他區域,則隱藏軟鍵盤。 主要程式碼如下: override fun dispatchTouchEvent(ev: MotionEvent?): Boolean { if (ev!!.getAction() ==

Android仿朋友圈九宮格圖片展示自定義控制元件支援縮放動畫~

一直對微信朋友圈九宮格圖片顯示控制元件比較好奇,找到一篇介紹相關騷操作的部落格 部落格雖好但是不夠完美,缺少點選圖片預覽頁面和縮放動畫,作為一個不斷追求完美主義的人,我想把這個控制元件結合到專案中而不是單純作為一個控制元件。 下面是我的實現效果圖: (

Android仿QQ群頭像合成

原文地址:https://www.jb51.net/article/130296.htm 效果圖: 作為程式設計師,首先會評估下工作量吧。在產品眼裡,就是把圖片合成一起嘛,有啥難度嗎?所以工作時間決定了你能做成什麼樣吧 方案分析: 方案1、直接寫成佈局,然後按照不同的佈局載入不

Android 仿聯絡人Demo(自定義ViewViewgroup)

上週在某部落格發現博主分享了一篇很經典的程式---------聯絡人效果。感覺很神祕很強大,但在閱讀和理解博主的demo的同時也發現了一些冗餘和不完美。於是帶著寶寶的痛一咬牙自己開工了,大約花了一週的時間(當然我白天還得上班的),做出了這種效果。如下圖: now跟著

Android 仿popuwindow彈窗呼叫只需要一個方法以及4.4系統popuwindow外部不響應解決辦法

對於popuwindow大家都熟悉,他給Dialog的區別就是外部可以點選消失,一些使用者提示、使用者指引基本上用的都是這個控制元件,我用這個控制元件實現了微信分享的下部彈窗,效果挺好,使用起來也比較流暢,佈局樣式,都可以根據自己的需求進行更改,很不錯的一個方法,希望能幫到大

Android 仿通訊錄功能好友排序 + 字母索引

一、效果圖展示 二、功能特點 1.好友排序:按照拼音順序對好友進行排序,相容英文數字符號等 2.字母索引:右側字母導航條,既可拖動也可點選,聯動ListView滑動 三、實現 接下來就讓我們一步步顯示這個效果吧。 1.右側字母索引的導航條 這個我們可

Android仿圖片編輯庫你想要的功能這裡都有

最近專案需要,寫了一個和微信中圖片編輯功能類似的圖片編輯庫,除去問題操作上擯棄掉不方便的手勢操作外,其餘微信中的核心功能全部一致,保留了微信中塗鴉、馬賽克、文字等隨時隨著圖片縮放的功能,這點是我所找的庫都不提供的功能,也是我從零去完成這個圖片編輯庫的原因。

Android 仿通訊錄 導航分組列表-下】自定義View為RecyclerView打造右側索引導航欄IndexBar

本篇文章已授權微信公眾號 guolin_blog (郭霖)獨家釋出 一 概述 在上篇文章(http://blog.csdn.net/zxt0601/article/details/52355199)裡,我們用ItemDecoration為Recy

android仿紅包動畫、Kotlin綜合應用、Xposed模塊、炫酷下拉視覺、UC瀏覽器滑動動畫等源碼

架構分析 body oot googl short html 博文 urn 管理 Android精選源碼 仿微信打開紅包旋轉動畫 使用Kotlin編寫的Android應用,內容你想象不到 Android手機上的免Root Android系統日誌Viewer 一個能讓微

android 仿表情雨下落!

block private www 事件觸發 dog ase 之間 apk ces 文章鏈接:https://mp.weixin.qq.com/s/yQXn-YjEFSW1X7A7CcuaVg 眾所周知,微信聊天中我們輸入一些關鍵詞會有表情雨下落,比如輸入「生日快樂」「

Android 仿qq未讀訊息角標 BadgeView的使用

新增依賴: compile 'q.rorbin:badgeview:1.1.3' 使用方法: TextView textview = (TextView) findViewById(R.id.textview); new QBadgeView(this)

Android仿首頁下拉顯示小程式列表

花點時間重新熟悉一下AndroidUI方面的東西,把古董PullToRefreshView又擼了一遍,技術這種東西真是忘得快啊...在基礎上新增一點東西,粗糙地實現了仿微信首頁下拉顯示小程式列表的樣式,是的,粗糙粗糙... PullToRefreshView原始的實現思路: 1.垂直方向的L

Android仿右側頂部下拉對話方塊

我們使用微信都知道,其右側頂部有一個下拉對話方塊,我們可以執行新增好友,掃一掃等功能,今天我們就來模仿實現一下這個功能(實現的方式有很多種,我今天只說一種藉助透明主題Activity的方式實現);實現的效果如下: 下面就來說一說實現的思路(重要): 第一步:建立彈

Android仿文章懸浮窗效果

序言 前些日子跟朋友聊天,朋友Z果粉,前些天更新了微信,說微信出了個好方便的功能啊,我問是啥功能啊,看看我大Android有沒有,他說現在閱讀公眾號文章如果有人給你發微信你可以把這篇文章當作懸浮窗懸浮起來,方便你聊完天不用找繼續閱讀,聽完是不是覺得這叫啥啊,我大

Android 仿介面 使用RadioGroup+ViewPager實現底部按鈕切換以及滑動

先來效果圖哈哈 ![在這裡插入圖片描述](https://img-blog.csdn.net/2018100916182717?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjMwNjcwN

Android 仿錄製短視訊不使用 FFmpeg

轉載請標明出處與作者:https://www.jianshu.com/p/2cb7b0110fde 專案中原本就有錄製短視訊的功能,使用的是 # qdrzwd/VideoRecorder 這個專案,但是該專案不支援 targetSdkVersion 22以上的版本,而現在各大

Android 仿對話列表滑動刪除效果

微信對話列表滑動刪除效果很不錯的,借鑑了github上SwipeListView(專案地址:https://github.com/likebamboo/SwipeListView),在其上進行了一些重構,最終實現了微信對話列表滑動刪除效果。 實現原理 1.通過ListVi

android仿聯絡人索引列表

前言   因為自己在做的一個小軟體裡面需要用到從A-Z排序的ListView,所以自然而然的想到了微信的聯絡人,我想要的就是那樣的效果。本來沒打算自己去寫,想要第三方寫好的東西,搜了幾個之後發現有的太複雜了,有的簡單是簡單,但是不符合我的要求,所以我就來個整合