HorizontalScrollViewをカスタマイズして、QQメッセージリスト効果を実現します

序文

以前はDrawerLayoutを使用してサイドスリップバーを実装していましたが、今ではDrawerLayoutが20dpのエッジでしか引き出せないことに耐えられません。DrawerLayoutとカスタムHorizo​​ntalScrollViewの使用の違いを簡単に比較します。

DrawerLayout:
長所:実装が簡単で、DrawerLayoutのスライドを介してイベントをリッスンするだけです。
短所:エッジの20dpのみがスライドをトリガーできます。

カスタムHorizo​​ntalScrollView:
長所:アイテム全体がスライドをトリガーできます(QQメッセージリストと同じ効果を実現するため)
短所:実装するのが少し面倒で、アイテムにクリックイベントを書き込む必要があります(イベントをスキップできますが、フォーカスを取得する必要があります)。スライドバーが利用できない場合があり、クリックして取得できます

エフェクト画像

ここに写真の説明を挿入

カスタムビュー

実施原則

これはカスタムHorizo​​ntalScrollViewで、これは主に、全体として水平方向にスライドできるHorizo​​ntalScrollViewの固有の機能を使用しています。

よるonScrollChangedドラッグバーのうちのスライド距離を制御する距離

onTouchEvent2人のリスナーを達成し、達成するために:動作を停止すると、スライドバーの状態を判断し、全体のスライド操作がイジェクトバーが半分以上のバーをスライドからスライドバーを引き出すと、時にスリップを停止するに置きます引き抜くバーの距離がスライディングバーよりも短い場合は、操作を停止し、スライディングバーを再度非表示にします。

SideBarScrollView.java

public class SideBarScrollView extends HorizontalScrollView {
    
    

    private LinearLayout slide;//侧滑栏
    private int slideWidth;//侧滑最大限度
    private SideBarScrollView.onMovingListener onMovingListener;//监听器

    public SideBarScrollView(Context context) {
    
    
        super(context, null);
    }

    public SideBarScrollView(Context context, AttributeSet attrs) {
    
    
        super(context, attrs, 0);
    }

    public SideBarScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
    
    
        super(context, attrs, defStyleAttr);
        this.setOverScrollMode(OVER_SCROLL_NEVER);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    
    
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        slide = findViewById(R.id.ll_slide);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
    
    
        super.onLayout(changed, l, t, r, b);
        //获取侧滑栏的宽度,即滑动的范围
        slideWidth = slide.getWidth();
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
    
    
        super.onScrollChanged(l, t, oldl, oldt);
        //根据拖动改变侧滑栏显示的宽度
        slide.setTranslationX(l - slideWidth);
    }

    //定义一个监听
    public interface onMovingListener {
    
    
        void onMove(SideBarScrollView sideBarScrollView);

        void onOpen(SideBarScrollView sideBarScrollView);
    }

    //定义监听
    public void setListener(onMovingListener onMovingListener) {
    
    
        this.onMovingListener = onMovingListener;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
    
    
        switch (ev.getAction()) {
    
    
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                //正在操作时
                onMovingListener.onMove(this);
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                //停止操作时
                //判断拖动的距离有没有超过侧滑栏的一半(超过则整个弹出,否则关闭)
                if (getScrollX() > slideWidth / 2) {
    
    
                    this.smoothScrollTo(slideWidth, 0);
                    onMovingListener.onOpen(this);
                } else {
    
    
                    this.smoothScrollTo(0, 0);
                }
                return true;//停止操作时返回true
        }
        return super.onTouchEvent(ev);
    }
}

RecyclerViewで使用する

項目

XMLレイアウトファイル
ここでは、com.yjx.mystudylife.Features.SideBar.SideBarScrollViewカスタムビューで
RelativeLayoutの性質によるandroid:layout_toRightOf=""バーをスライド側を制御するためには、通常のコンテンツの右側に常にあります
注:ここの左側のコンテンツのLinearLayoutは背景に指定する必要があります。そうしないと、サイドスライドバーに問題が発生します。

<?xml version="1.0" encoding="utf-8"?>
<com.yjx.mystudylife.Features.SideBar.SideBarScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="50dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:id="@+id/ll_slide"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_toRightOf="@id/ll_left">

            <TextView
                android:id="@+id/txv_top"
                android:layout_width="80dp"
                android:layout_height="match_parent"
                android:background="#F5DF1D"
                android:gravity="center"
                android:text="置顶" />

            <TextView
                android:id="@+id/txv_del"
                android:layout_width="80dp"
                android:layout_height="match_parent"
                android:background="#ff00"
                android:gravity="center"
                android:text="删除" />
        </LinearLayout>

        <LinearLayout
            android:id="@+id/ll_left"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#fff">

            <TextView
                android:id="@+id/txv_name"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"
                android:textSize="18sp" />
        </LinearLayout>

    </RelativeLayout>

</com.yjx.mystudylife.Features.SideBar.SideBarScrollView>
RecyclerView的アダプター

ここでは、カスタムビューで記述されたインターフェイスを直接実装し、2つのインターフェイスを介して実装します
onOpen::サイドスライドバーが開いたら、開いたアイテムを割り当てます
onMove:モバイルモニタリング、移動中のアイテムがある場合は、現在移動中のアイテムと開いているアイテムを判断しますアイテムが同じであるかどうか、一貫性がない場合は、前のサイドスライドバーを閉じます

itemViewを監視する必要があります:((SideBarScrollView) itemView).setListener(AdapterSideBar.this);ここでは強制的に回転させる必要があります

holder.llLeft.getLayoutParams().width = activity.getWindowManager().getDefaultDisplay().getWidth();ここでは、通常の表示コンテンツの幅を設定する必要があります

public class AdapterSideBar extends RecyclerView.Adapter<AdapterSideBar.ViewHolder> implements SideBarScrollView.onMovingListener {
    
    

    Activity activity;
    List<String> list;
    private SideBarScrollView scrollView;

    public AdapterSideBar(Activity activity, List<String> list) {
    
    
        this.activity = activity;
        this.list = list;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    
    
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.sidebar_item, parent, false);
        ViewHolder viewHolder = new ViewHolder(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
    
    
        holder.llLeft.getLayoutParams().width = activity.getWindowManager().getDefaultDisplay().getWidth();
        holder.txvName.setText(list.get(position));
        //左边正常内容需要有监听事件,抢夺焦点
        holder.llLeft.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View view) {
    
    

            }
        });
        holder.txvTop.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View view) {
    
    
                Toast.makeText(activity, "置顶", Toast.LENGTH_SHORT).show();
            }
        });
        holder.txvDel.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View view) {
    
    
                Toast.makeText(activity, "删除", Toast.LENGTH_SHORT).show();
            }
        });
    }

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

    @Override
    public void onMove(SideBarScrollView sideBarScrollView) {
    
    
        if (scrollView != null && scrollView != sideBarScrollView) {
    
    
            scrollView.smoothScrollTo(0, 0);
            scrollView = null;
        }
    }

    @Override
    public void onOpen(SideBarScrollView sideBarScrollView) {
    
    
        scrollView = sideBarScrollView;
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
    
    
        private TextView txvTop;
        private TextView txvDel;
        private LinearLayout llLeft;
        private TextView txvName;

        public ViewHolder(@NonNull View itemView) {
    
    
            super(itemView);
            txvTop = (TextView) itemView.findViewById(R.id.txv_top);
            txvDel = (TextView) itemView.findViewById(R.id.txv_del);
            llLeft = (LinearLayout) itemView.findViewById(R.id.ll_left);
            txvName = (TextView) itemView.findViewById(R.id.txv_name);
            ((SideBarScrollView) itemView).setListener(AdapterSideBar.this);
        }
    }
}

実装される主な機能は掲載されていますが、始まりと終わりのある人間として、通常のRecyclerViewは次のアクティビティで実現されます。

RecyclerViewActivity

これがRecyclerViewの簡単な実装です

for (int i = 0; i < 5; i++) {
    
    
            list.add(i + "");
        }
        adapterSideBar = new AdapterSideBar(this, list);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
        recyclerView.setAdapter(adapterSideBar);

おすすめ

転載: blog.csdn.net/qq_44720366/article/details/108409919