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(ドラッグアンドドロップ)の使用例



デフォルトでは、 FAM



background



がないため、好きなものを使用できます。 また、 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()



使用すると、ユーザーがFAM



fam_minimize_direction



属性fam_minimize_direction



および以下で説明するインデントをドラッグした場所を考慮して、それぞれ展開状態および折りたたみ状態のtranslationY



を計算できます。







閉じてドラッグ



正確で美しい作業のために、 FAM



はボタン( ImageView



)があり、ユーザーは状況依存アクションモードを閉じるか、画面の別の部分に垂直にドラッグできます(目的のリストアイテムがブロックされている場合)。 FAM



は、水平方向にドラッグして閉じることもできます(スワイプして閉じます)。







FAM



LinearLayout



で、作成中にボタンを追加( 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



は、タッチの開始点を記憶し、移動するとtranslationX



translationY



それぞれタッチに設定します。 ユーザーがドラッグボタン( 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ライブラリディレクトリ)で入手できます。 FAM



appディレクトリ)を使用したデモアプリケーションもあります。







FloatingActionMode



自体とFloatingActionModeBehavior



open



クラスとして定義されてopen



ため、必要に応じてアップグレードできます。 主要なFloatingActionMode



メソッドもopen



として定義されていopen









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








All Articles