列表粘性分组之按首字母分组国家选区号
Android原生版本
直接先看UI图,效果如下

 本来看起来也不难,我就想着上面常用区号那块不动,下面的列表滑动就行,但IOS说他滑动的时候上面也滑上去了,好吧,这也行;但最终效果做出来后,IOS滑动后会有按照国家名称首字母进行粘性分组,好吧,为了提升自己,我也决定做得跟IOS一样,不说废话了,直接上代码
 引入流布局控件
//流布局
api 'com.google.android:flexbox:1.0.0'
 
布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:id="@+id/rl_content"
    android:layout_width="match_parent"
    android:layout_height="@dimen/dp_area_code_pop_height"
    app:defaultColor="@color/white"
    app:topLeftRadius="@dimen/dp_10"
    app:topRightRadius="@dimen/dp_10"
    tools:background="@color/white">
    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_gravity="center"
        android:paddingVertical="@dimen/dp_20"
        android:text="@string/sel_international_code"
        android:textColor="@color/col_3a3b3d"
        android:textSize="@dimen/sp_18" />
    <com.yunqu.quyun_res.widget.StatusLayout
        android:id="@+id/status"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv_title"
        app:status="LOADING"
        app:toolsStatus="NORMAL">
        <ProgressBar
            style="?android:attr/progressBarStyleSmall"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            app:layout_status="LOADING" />
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_status="NORMAL">
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/rv_general"
                android:background="@color/white"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:paddingHorizontal="@dimen/dp_20"
                android:paddingVertical="@dimen/dp_10"
                tools:itemCount="4"
                tools:listitem="@layout/item_general_code" />
        </FrameLayout>
    </com.yunqu.quyun_res.widget.StatusLayout>
    <View
        android:id="@+id/v_divider"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_0_5"
        android:layout_above="@id/tv_cancel"
        android:background="@color/col_e0e7ee" />
    <Button
        android:id="@+id/tv_cancel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="@color/white"
        android:gravity="center"
        android:paddingVertical="@dimen/dp_17"
        android:text="@string/cancel"
        android:textColor="@color/col_3a3b3d"
        android:textSize="@dimen/sp_16"
        app:textPressedColor="@color/col_acb2b8" />
    <com.yunqu.quyun_res.widget.TenXuLetterBar
        android:id="@+id/txlb"
        android:layout_width="@dimen/dp_15"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv_title"
        android:layout_alignBottom="@id/v_divider"
        android:layout_alignParentEnd="true"
        android:layout_marginTop="@dimen/dp_70"
        android:layout_marginEnd="@dimen/dp_20"
        android:layout_marginBottom="@dimen/dp_10"
        android:minHeight="@dimen/dp_area_code_mh"
        app:txlb_item_background_def="@drawable/bg_letter_def"
        app:txlb_item_background_sel="@drawable/bg_letter_sel"
        app:txlb_item_text_color_def="@color/col_9b9b9b"
        app:txlb_item_text_color_sel="@color/white" />
    <TextView
        android:id="@+id/tv_letter"
        android:layout_width="@dimen/dp_55"
        android:layout_height="@dimen/dp_55"
        android:layout_centerInParent="true"
        android:layout_gravity="center"
        android:background="@drawable/bg_circle_80000000"
        android:gravity="center"
        android:textColor="@color/white"
        android:textSize="18sp"
        android:visibility="gone"
        tools:visibility="visible" />
</RelativeLayout>
 
item_common_code.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingBottom="@dimen/dp_10"
    tools:ignore="MissingDefaultResource">
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_commons"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:nestedScrollingEnabled="false"
        tools:itemCount="2"
        tools:listitem="@layout/item_common_code" />
</FrameLayout>
 
item_common_code_tip.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:ignore="MissingDefaultResource">
    <TextView
        android:id="@+id/tv_common_tip"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/common_code"
        android:textColor="@color/col_9b9b9b"
        android:textSize="@dimen/sp_14" />
</FrameLayout>
 
item_general_code.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <TextView
        android:id="@+id/tv_code"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingVertical="@dimen/dp_12"
        android:includeFontPadding="false"
        android:textColor="@color/col_111212"
        android:textSize="@dimen/sp_14"
        tools:text="中国大陆+86" />
</LinearLayout>
 
item_general_code_group.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    tools:ignore="MissingDefaultResource">
    <LinearLayout
        android:id="@+id/ll_letter"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        tools:ignore="UselessParent">
        <TextView
            android:id="@+id/tv_letter"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/col_111212"
            android:textSize="@dimen/sp_14"
            android:textStyle="bold"
            tools:text="A" />
        <View
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_0_5"
            android:layout_marginTop="@dimen/dp_10"
            android:background="@color/col_e0e7ee" />
    </LinearLayout>
</LinearLayout>
 
其中com.yunqu.quyun_res.widget.StatusLayout控件是自定义的一个FrameLayout状态控件,这里就不放出来了,其实主要就是控制加载数据过程中的切换,根据逻辑用GONE和VISIBLE也是一样的
com.yunqu.quyun_res.widget.TenXuLetterBar控件代码如下
public class TenXuLetterBar extends View {
   
    private static final String TAG = "TenXuLetterBar";
    //    private final List<String> mLetters = new ArrayList<>();
    private final String[] mLettersHadWell = new String[]{
   "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"
            , "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "#"};
    private final String[] mLetters = new String[]{
   "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"
            , "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
    private final Paint mPaint;
    private Drawable mItemBackgroundDef;
    private Drawable mItemBackgroundSel;
    private final int mItemTextColorDef;
    private final int mItemTextColorSel;
    private final boolean mNeedWell;
    //    private int mLetterWidth;
    private int mLetterIndex = -1;
    private OnLetterChangeListner onLetterChangeListener;//选中字母后的回调
    public TenXuLetterBar(Context context) {
   
        this(context, null);
    }
    public TenXuLetterBar(Context context, AttributeSet attrs) {
   
        this(context, attrs, 0);
    }
    public TenXuLetterBar(Context context, AttributeSet attrs, int defStyleAttr) {
   
        super(context, attrs, defStyleAttr);
        TypedArray typedArray =
                context.obtainStyledAttributes(attrs, R.styleable.TenXuLetterBar);
        mItemBackgroundDef = typedArray.getDrawable(
                ![[CSAWQual 2019]Web_Unagi ---不会编程的崽](https://img-blog.csdnimg.cn/direct/944a253cafd94adfbd956d3de7361107.png)


















