Android RecyclerView实现(SideBar,通讯录,国家地区选择器)

前言

使用RecyclerView实现通讯录/选择国家地区功能,点击字母指定位置的数据置顶显示

逻辑

采用两个RecyclerView进行联动,左边显示数据,右边显示字母。计算右边的RecyclerView手指滑动过程中的position,需计算每个item的高度,再用屏幕高度去除这个高度得到一个因素,用motionEvent.getY()除这个因素得到当前的位置currentPosition。话不多数,上代码:

/**
 * Created by 小跑一年
 * on 2020/5/06
 * des: 选择国家地区
 */
public class SelectCountryAct extends AppCompatActivity {

    @BindView(R.id.rv_content)
    RecyclerView rvContent;
    @BindView(R.id.rv_letter)
    RecyclerView rvLetter;

    private Unbinder mUnbinder;
    private List<SelectCountryModel> dataList;
    private List<String> strList;
    private List<Integer> posList;
    private int perTextHeight;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_select_country);
        mUnbinder = ButterKnife.bind(this);

        perTextHeight = ScreenUtils.getScreenHeight(SelectCountryAct.this) / ScreenUtils.dp2px(SelectCountryAct.this, 16);

        initData(); //数据源

        initWidget();
    }

    @SuppressLint("ClickableViewAccessibility")
    private void initWidget() {
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        rvContent.setLayoutManager(linearLayoutManager);
        rvSearchContent.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
        rvLetter.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
        CommonRecycleviewAdapter adapter = new CommonRecycleviewAdapter<SelectCountryModel>(dataList, SelectCountryAct.this, R.layout.item_select_country) {
            @Override
            protected void onBindView(RecycleViewHolder holder, int position) {
                View viewLine = holder.getView(R.id.view_line);
                TextView tvCountryName = holder.getView(R.id.tv_country_name);
                TextView tvCountryNum = holder.getView(R.id.tv_country_num);
                TextView tvCountryLetter = holder.getView(R.id.tv_country_letter);
                tvCountryName.setText(dataList.get(position).getCountryName());
                tvCountryNum.setText(dataList.get(position).getCountryCode());
                tvCountryLetter.setText(dataList.get(position).getShortName());
                if (position > 0 && dataList.get(position).getShortName().equals(dataList.get(position - 1).getShortName())) {
                    tvCountryLetter.setVisibility(View.GONE);
                    viewLine.setVisibility(View.VISIBLE);
                } else {
                    viewLine.setVisibility(View.GONE);
                    tvCountryLetter.setVisibility(View.VISIBLE);
                }
            }
        };
        rvContent.setAdapter(adapter);

        CommonRecycleviewAdapter adapter2 = new CommonRecycleviewAdapter<String>(strList, SelectCountryAct.this, R.layout.item_select_country_letter) {
            @Override
            protected void onBindView(RecycleViewHolder holder, int position) {
                TextView tvCountryLetter = holder.getView(R.id.tv_country_letter);
                tvCountryLetter.setText(strList.get(position));
            }
        };
        rvLetter.setAdapter(adapter2);
        adapter.setOnItemClickListener(new CommonRecycleviewAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) { //选中国家地区信息
            }

            @Override
            public void onItemLongClick(View view, int position) {
            }
        });
        adapter2.setOnItemClickListener(new CommonRecycleviewAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                //保证点击后数据置顶显示,使用rvLetter.scrollToPosition(position)或rvLetter.smoothScrollToPosition(position),左边数据显示在屏幕底部
                linearLayoutManager.scrollToPositionWithOffset(posList.get(position), 0);
            }

            @Override
            public void onItemLongClick(View view, int position) {
            }
        });

        rvLetter.setOnTouchListener(new View.OnTouchListener() { //处理手指上下滑动获取position
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                float y = motionEvent.getY();
                int currentPosition = (int) (y / perTextHeight);

                currentPosition = currentPosition < 0 ? 0 : currentPosition < posList.size() ? currentPosition : posList.size() - 1;


                linearLayoutManager.scrollToPositionWithOffset(posList.get(currentPosition), 0);
                return true;
            }
        });
    } 

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mUnbinder != null) {
            mUnbinder.unbind();
        }
    }
}

activity_select_country.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/clo_f8f8f8"
    android:focusable="true"
    android:focusableInTouchMode="true">

    <!--  android:textCursorDrawable="@color/black_4D"  -->
    <EditText
        android:id="@+id/et_search"
        android:layout_width="match_parent"
        android:layout_height="@dimen/distance_36dp"
        android:layout_marginLeft="@dimen/distance_12dp"
        android:layout_marginTop="@dimen/distance_8dp"
        android:layout_marginRight="@dimen/distance_12dp"
        android:layout_marginBottom="@dimen/distance_8dp"
        android:autofillHints="no"
        android:background="@drawable/bg_white_4dp"
        android:hint="@string/search_country"
        android:imeOptions="actionSearch"
        android:inputType="text"
        android:paddingLeft="@dimen/distance_40dp"
        android:textColor="@color/black_20"
        android:textColorHint="@color/black_4D"
        android:textSize="14dp"
        android:theme="@style/MyEditText" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/distance_12dp"
        android:layout_marginTop="@dimen/distance_6dp"
        android:src="@mipmap/search" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/et_search"
        android:scrollbars="none" />

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_below="@+id/et_search"
        android:layout_alignParentRight="true"
        android:background="@color/transparent">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_letter"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:background="@color/transparent"
            android:scrollbars="none" />
    </RelativeLayout>

    <View
        android:id="@+id/view_bg"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/et_search"
        android:background="@color/black_66"
        android:visibility="gone" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_search_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/et_search"
        android:background="@color/white"
        android:scrollbars="none"
        android:visibility="gone" />
</RelativeLayout>

item_select_country.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:orientation="vertical">

    <View
        android:id="@+id/view_line"
        android:layout_marginLeft="@dimen/distance_12dp"
        android:background="@color/clo_1A221E1F"
        android:layout_width="match_parent"
        android:layout_height="@dimen/height_1px"/>

    <TextView
        android:id="@+id/tv_country_letter"
        android:layout_width="match_parent"
        android:layout_height="32dp"
        android:background="@color/clo_f8f8f8"
        android:gravity="center_vertical"
        android:paddingLeft="@dimen/distance_12dp"
        android:textColor="@color/black_99"
        android:textSize="16dp" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="@dimen/distance_12dp">

        <TextView
            android:id="@+id/tv_country_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/white"
            android:textColor="@color/black_20"
            android:textSize="16dp" />

        <TextView
            android:id="@+id/tv_country_num"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentEnd="true"
            android:layout_alignParentRight="true"
            android:background="@color/white"
            android:paddingRight="@dimen/distance_30dp"
            android:textColor="@color/black_4D"
            android:textSize="14dp" />
    </RelativeLayout>
</LinearLayout>

item_select_country_letter.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/transparent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_country_letter"
        android:textColor="@color/clo_DD8675"
        android:paddingRight="@dimen/distance_9dp"
        android:paddingLeft="@dimen/distance_12dp"
        android:textSize="12dp"
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="@dimen/distance_16dp" />
</LinearLayout>

后记

后续跟进中.....

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值