序文
以前はDrawerLayoutを使用してサイドスリップバーを実装していましたが、今ではDrawerLayoutが20dpのエッジでしか引き出せないことに耐えられません。DrawerLayoutとカスタムHorizontalScrollViewの使用の違いを簡単に比較します。
DrawerLayout:
長所:実装が簡単で、DrawerLayoutのスライドを介してイベントをリッスンするだけです。
短所:エッジの20dpのみがスライドをトリガーできます。
カスタムHorizontalScrollView:
長所:アイテム全体がスライドをトリガーできます(QQメッセージリストと同じ効果を実現するため)
短所:実装するのが少し面倒で、アイテムにクリックイベントを書き込む必要があります(イベントをスキップできますが、フォーカスを取得する必要があります)。スライドバーが利用できない場合があり、クリックして取得できます
エフェクト画像
カスタムビュー
実施原則
これはカスタムHorizontalScrollViewで、これは主に、全体として水平方向にスライドできるHorizontalScrollViewの固有の機能を使用しています。
よるonScrollChanged
ドラッグバーのうちのスライド距離を制御する距離
onTouchEvent
2人のリスナーを達成し、達成するために:動作を停止すると、スライドバーの状態を判断し、全体のスライド操作がイジェクトバーが半分以上のバーをスライドからスライドバーを引き出すと、時にスリップを停止するに置きます引き抜くバーの距離がスライディングバーよりも短い場合は、操作を停止し、スライディングバーを再度非表示にします。
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);