FloatingActionMode-Androidのコンテキストアクションバー

リストアイテムを使用したコンテキストアクションは、Androidアプリケーションで広く使用されています。 リストの複数の要素またはすべての要素を選択し、選択したすべての要素にアクションを一度に適用すると非常に便利です。 たとえば、削除します。


Androidアプリケーションでは、これにActionModeを使用できます。これにより、選択した要素で利用可能なアクションをToolbar上に表示できます。 そこで、現在選択されている要素の数やその他の有用な情報をユーザーに表示できます。 それは便利で見栄えが良いですが、場合によってはToolbar自体に表示される情報が重要であり、非表示にしたくないでしょう。 たとえば、ユーザーの名前と写真、リストに表示されるメッセージのリストがあります。 一部のメッセージを強調表示する場合、これらのメッセージの宛先となるユーザーの名前を確認すると便利です。


この場合、 Toolbarをブロックすることなく、リスト自体の上にリスト項目を含むコンテキストアクションパネルを表示できます。 この記事では、このようなコンテキストアクションパネルの作成について説明します。


CustomView- FloatingActionModeまたは単にFAMと呼ばれるコンテキストアクションのパネルを開発しました。


芸術
実行中のFloatingActionMode (下からロック)


ビデオ-FloatingActionModeの使用例(以下に修正)


コメントでは、ユーザーが画面の周りにパネルをドラッグすることはあまり便利ではない可能性があることが指摘されたため、上のスクリーンショットとビデオに示すように、画面の下部に固定できます。 (これを行うには、 android:layout_gravity="bottom"およびapp:fam_can_drag="false"の属性を指定します)。


同時に、次のスクリーンショットとビデオに示すように、ユーザーが画面上でFAMを移動できるようにすることができます。


芸術
実行中のFloatingActionMode


ビデオ-FloatingActionMode(ドラッグアンドドロップ)の使用例


デフォルトでは、 FAMbackgroundがないため、好きなものを使用できます。 また、 android:translationZ="8dp"属性android:translationZ="8dp"を使用して、API> = 21のデバイスでシャドウを作成できます。


XML属性


マークアップファイルを使用してFAMを構成するために、いくつかの特別な属性が定義されていますが、プログラムで変更することもできます。



FAMにはOnCloseListenerもあります。これにより、ユーザーOnCloseListener FAM OnCloseListenerときに特定のアクションを実行できます(たとえば、リストから項目を選択解除します)。


主なアクション


FAMの主なアクションは、開く/閉じる、折り畳む/展開することです。 開くと表示されて展開し、閉じると折りたたまれて消えます。


FAMの展開にFAMアニメーションFAM伴います。その間に、親ViewGroupの上端または下端(この端はfam_minimize_direction属性によって設定されます)からマークアップファイルで指定された位置に移動します。 アニメーションは次のように定義されます。


 animate() .scaleY(1f) .scaleX(1f) .translationY(calculateArrangeTranslationY()) .alpha(1f) 

最小化すると、アニメーションは「反対方向に」実行されます。


 animate() .scaleY(0.5f) .scaleX(0.5f) .translationY(calculateMinimizeTranslationY()) .alpha(0.5f) 

メソッドcalculateArrangeTranslationY()およびcalculateMinimizeTranslationY()使用すると、ユーザーがFAMfam_minimize_direction属性fam_minimize_directionおよび以下で説明するインデントをドラッグした場所を考慮して、それぞれ展開状態および折りたたみ状態のtranslationYを計算できます。


閉じてドラッグ


正確で美しい作業のために、 FAMはボタン( ImageView )があり、ユーザーは状況依存アクションモードを閉じるか、画面の別の部分に垂直にドラッグできます(目的のリストアイテムがブロックされている場合)。 FAMは、水平方向にドラッグして閉じることもできます(スワイプして閉じます)。


FAMLinearLayoutで、作成中にボタンを追加( fam_drag_button )およびドラッグ( fam_close_button )します。 FAMを閉じる/ドラッグする機能は、アプリケーションの実行中にオン/オフを切り替えることができるため、これらのボタンを含むLinearLayoutは、 android:animateLayoutChanges="true"属性android:animateLayoutChanges="true"ます。


FAMマークアップ
 <?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android"> <LinearLayout android:layout_width="wrap_content" android:layout_height="?attr/actionBarSize" android:animateLayoutChanges="true" android:layout_gravity="center_vertical"> <ImageView android:id="@+id/fam_close_button" android:layout_width="?attr/actionBarSize" android:layout_height="?attr/actionBarSize" android:layout_gravity="center_vertical" android:background="@drawable/fam_image_button_background" android:scaleType="center" android:src="@drawable/fam_ic_close_white_24dp"/> <ImageView android:id="@+id/fam_drag_button" android:layout_width="?attr/actionBarSize" android:layout_height="?attr/actionBarSize" android:layout_gravity="center_vertical" android:background="@drawable/fam_image_button_background" android:scaleType="center" android:src="@drawable/fam_ic_drag_white_24dp"/> </LinearLayout> </merge> 

ドラッグメカニズムはOnTouchListenerを使用して実装されますOnTouchListenerは、タッチの開始点を記憶し、移動するとtranslationXtranslationYそれぞれタッチに設定します。 ユーザーがドラッグボタン( fam_drag_button )をfam_drag_buttonと、 FAMは元の水平位置に戻り、ユーザーがFAM十分に水平方向にドラッグすると、 this@FloatingActionMode.close()メソッドがthis@FloatingActionMode.close()ます。


オンタッチリスナー
 fam_drag_button.setOnTouchListener(object : OnTouchListener { var prevTransitionY = 0f var startRawX = 0f var startRawY = 0f override fun onTouch(v: View, event: MotionEvent): Boolean { if (!this@FloatingActionMode.canDrag) { return false } val fractionX = Math.abs(event.rawX - startRawX) / this@FloatingActionMode.width when (event.actionMasked) { MotionEvent.ACTION_DOWN -> { this@FloatingActionMode.fam_drag_button.isPressed = true startRawX = event.rawX startRawY = event.rawY prevTransitionY = this@FloatingActionMode.translationY } MotionEvent.ACTION_MOVE -> { this@FloatingActionMode.maximizeTranslationY = prevTransitionY + event.rawY - startRawY translationX = event.rawX - startRawX if (canDismiss) { val alpha = if (fractionX < dismissThreshold) 1.0f else Math.pow(1.0 - (fractionX - dismissThreshold) / (1 - dismissThreshold), 4.0).toFloat() this@FloatingActionMode.alpha = alpha } } MotionEvent.ACTION_UP -> { fam_drag_button.isPressed = false this@FloatingActionMode.animate().translationX(0f) .duration = animationDuration if (canDismiss && fractionX > dismissThreshold) { this@FloatingActionMode.close() } } } return true } }) 

CoordinatorLayout使用


calculateMinimizeTranslationY()メソッドとcalculateMinimizeTranslationY()メソッドは、上下のインデントを考慮して正しいFAM位置を決定すると以前に言われました。 これらのパディングは、 CoordinatorLayout.Behavior拡張であるFloatingActionModeBehaviorを使用して計算されます。これは、上部パディングをAppBarLayoutの高さにAppBarLayoutし、下部パディングをAppBarLayoutの表示部分の高さに設定しSnackbar.SnackbarLayout


また、 FloatingActionModeBehavior使用すると、 FAMスクロールFAM応答し、下にスクロールすると折り畳み、上にスクロールすると展開します(クイックリターンパターン)。


FloatingActionModeBehavior
  open class FloatingActionModeBehavior @JvmOverloads constructor(context: Context? = null, attrs: AttributeSet? = null) : CoordinatorLayout.Behavior<FloatingActionMode>(context, attrs) { override fun layoutDependsOn(parent: CoordinatorLayout?, child: FloatingActionMode?, dependency: View?): Boolean { return dependency is AppBarLayout || dependency is Snackbar.SnackbarLayout } override fun onDependentViewChanged(parent: CoordinatorLayout, child: FloatingActionMode, dependency: View): Boolean { when (dependency) { is AppBarLayout -> child.topOffset = dependency.bottom is Snackbar.SnackbarLayout -> child.bottomOffset = dependency.height - dependency.translationY.toInt() } return false } override fun onStartNestedScroll(coordinatorLayout: CoordinatorLayout?, child: FloatingActionMode?, directTargetChild: View?, target: View?, nestedScrollAxes: Int): Boolean { return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL } override fun onNestedScroll(coordinatorLayout: CoordinatorLayout, child: FloatingActionMode, target: View, dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int) { super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed) // FAM        View. var parent = target.parent while (parent != coordinatorLayout) { if (parent == child) { return } parent = parent.parent } if (dyConsumed > 0) { child.minimize(true) } else if (dyConsumed < 0) { child.maximize(true) } } } 

これは、マークアップファイルでFAMがどのように見えるかです。


 <android.support.design.widget.CoordinatorLayout> <android.support.design.widget.AppBarLayout> ... </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView app:layout_behavior="@string/appbar_scrolling_view_behavior"/> <com.qwert2603.floating_action_mode.FloatingActionMode android:id="@+id/floating_action_mode" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="@dimen/action_mode_margin" android:animateLayoutChanges="true" android:background="@drawable/action_mode_background" android:translationZ="8dp" app:fam_animation_duration="@integer/action_mode_animation_duration" app:fam_can_dismiss="true" app:fam_can_drag="true" app:fam_content_res="@layout/user_list_action_mode_2" app:fam_dismiss_threshold="0.35" app:fam_drag_icon="@drawable/ic_drag_white_24dp" app:fam_minimize_direction="nearest"/> </android.support.design.widget.CoordinatorLayout> 

ソースコード


FloatingActionModeのソースコードは、 GitHubライブラリディレクトリ)で入手できます。 FAMappディレクトリ)を使用したデモアプリケーションもあります。


FloatingActionMode自体とFloatingActionModeBehavior openクラスとして定義されてopenため、必要に応じてアップグレードできます。 主要なFloatingActionModeメソッドもopenとして定義されていopen


ご清聴ありがとうございました。 ハッピーコーディング!



Source: https://habr.com/ru/post/J319238/


All Articles