序文
マテリアル デザインは、さまざまなプラットフォームやデバイスにわたるビジュアル、モーション、インタラクションのデザインをユーザーにガイドするための包括的なガイドです。Android アプリでマテリアル デザインを使用するには、マテリアル デザイン仕様で定義されているガイドラインに従い、マテリアル デザイン サポート ライブラリで利用可能な新しいコンポーネントとスタイルを使用します。
主な記事
Android のマテリアル デザイン
Google - Androidのメンバーとして、その最も代表的なコントロールとエフェクトのいくつかは _マテリアル ライブラリ_ にパッケージ化されており、これにより開発者はマテリアル デザインを知らなくても独自のアプリケーションを簡単に具体化できます。もちろん、AndroidX ライブラリの一部のコンポーネントはマテリアル デザイン効果を実現することもできます。
BottomSheetDialogFragment コンポーネント
導入
このコンポーネントは、マテリアル デザインのボトム シートに属します。
編集
BottomSheetDialogFragment は、フローティング ダイアログの代わりに BottomSheetDialog を使用する DialogFragment のバージョンであるモーダル ボトム テーブルとして正式に解釈される AppCompatDialogFragment を継承します。
アドバンテージ
1. 独自のライフサイクルを持っています;
2. ページ全体を折りたたんだり、展開したり、破棄したりできます;
3. カスタム スタイルを柔軟に使用できます。
手順
implementation 'com.google.android.material:material:1.7.0'
Sync Gradle が正常に追加されたら、BottomSheetDialogFragment をプロジェクトに追加できます。これは、DialogFragment を継承する Dialog を通常に記述するのと同じように非常に簡単です。これは、その継承関係を上記で確認したためです。BottomSheetDialogFragment は AppCompatDialogFragment から継承し、AppCompatDialogFragment は DialogFragment から継承します
。このように、BottomSheetDialogFragment は DialogFragment のサブクラスであるため、DialogFragment のすべての特性を備えています。
要件を実現する
Dialog 部分の実装コード:
class DialogMore : BottomSheetDialogFragment() {
private var height : Int = 0
fun newInstance(): DialogMore {
return DialogMore()
}
fun setDialogHeight(height: Int): DialogMore {
this.height = height
return this
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NORMAL, R.style.StyleBottomSheetDialogBg)
}
override fun onStart() {
super.onStart()
//拿到系统的 bottom_sheet
val bottomSheetDialog = (dialog as BottomSheetDialog?)!!
val view =
bottomSheetDialog.delegate.findViewById<FrameLayout>(com.google.android.material.R.id.design\_bottom\_sheet)!!
val behavior = BottomSheetBehavior.from(view)
//设置弹出高度
behavior.peekHeight = height
view.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
behavior.isHideable = false
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState)
val view = LayoutInflater.from(context).inflate(R.layout.layout\_item\_dialog_more, null)
dialog.setContentView(view)
view.vDownClose.setOnClickListener {
dismiss()
}
return dialog
}
}
実装コードのこの部分は、下部のポップアップ ウィンドウを記述する通常の方法と似ていることがわかりますが、onStar() メソッドで BottomSheetBehavior を使用して、高さの制御やポップアップ ウィンドウの一部のプロパティ設定など、ポップアップ ウィンドウ自体の動作を制御できます。
onCreateDialog メソッドでは、ポップアップ ウィンドウのレイアウトを追加し、setContentView() メソッドを使用してレイアウトを取得します。このメソッドを書かないと、BottomSheetBehavior * val behavior = BottomSheetBehavior.from(view)* を取得したときにこの文が空になります。
また、ポップアップ ウィンドウの上部の角を丸くする必要があり、背景の影を削除するため、スタイルが追加されます。
<!--实现BottomSheetDialog圆角效果 且无背景阴影-->
<style name="StyleBottomSheetDialogBg" parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">@style/StyleBottomSheetStyleWrapper</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
<style name="StyleBottomSheetStyleWrapper" parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">@android:color/transparent</item>
</style>
ローカル スタイルは Dialog 実装コードで呼び出され、onCreate メソッドで setStyle() メソッドが使用されます。
また、レイアウトに丸い角を追加する必要があります。
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners
android:topLeftRadius="15dp"
android:topRightRadius="15dp" />
<solid android:color="@color/white" />
</shape>
スタイルは、定義したポップアップ ウィンドウ レイアウトの最も外側のレイアウトに追加できます。
ダイアログのサンプル レイアウトは次のとおりです。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout\_width="match\_parent"
android:layout\_height="wrap\_content"
android:background="@drawable/shape\_sheet\_dialog_bg"
android:orientation="vertical">
<LinearLayout
android:layout\_width="match\_parent"
android:layout\_height="wrap\_content"
android:layout_gravity="center"
android:paddingTop="10dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:gravity="center"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/vDownClose"
android:layout_width="48dp"
android:layout\_height="wrap\_content"
android:layout_marginStart="16dp"
android:layout_gravity="center"
android:src="@drawable/vector\_invite\_comment_close" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/vTitle"
android:layout\_width="match\_parent"
android:layout\_height="wrap\_content"
android:gravity="center"
android:text="More Content"
android:textColor="@color/black"
android:textSize="16sp"
android:textStyle="bold" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/vPositionEdit"
android:layout_width="48dp"
android:layout\_height="wrap\_content"
android:layout_marginEnd="16dp"
android:text=""
android:textColor="@color/black"
android:textSize="16sp" />
</LinearLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/vNsPosition"
android:layout\_width="match\_parent"
android:layout\_height="match\_parent">
<LinearLayout
android:layout\_width="match\_parent"
android:layout\_height="wrap\_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/llPtz"
android:layout\_width="match\_parent"
android:layout_height="8dp"
android:gravity="center"
android:orientation="horizontal">
</LinearLayout>
<LinearLayout
android:id="@+id/vLlPosition"
android:layout\_width="match\_parent"
android:layout\_height="match\_parent"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:layout\_width="match\_parent"
android:layout_height="300dp"
android:src="@mipmap/ic\_more\_content"
android:scaleType="fitCenter"/>
<androidx.appcompat.widget.AppCompatTextView
android:layout\_width="match\_parent"
android:layout\_height="wrap\_content"
android:layout_marginTop="20dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="1.可以弹出弹窗,且弹窗可以继续拉到顶部。"
android:textSize="14dp"
android:textColor="#FF666666"/>
<androidx.appcompat.widget.AppCompatTextView
android:layout\_width="match\_parent"
android:layout\_height="wrap\_content"
android:layout_marginTop="5dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="2.禁止下拉关闭弹窗,使下滑到固定位置后不会再动,关闭弹窗使用关闭按钮。"
android:textSize="14sp"
android:textColor="#FF666666"/>
</LinearLayout>
<LinearLayout
android:id="@+id/vLlNoPosition"
android:layout\_width="match\_parent"
android:layout_height="277dp"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/vNoPositionText"
android:layout\_width="match\_parent"
android:layout\_height="match\_parent"
android:layout_gravity="center"
android:gravity="center"
android:text="无更多内容"
android:textSize="14sp"
android:textColor="#FF666666"/>
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
ポップアップ ウィンドウの内側と外側のタッチ効果の競合が心配な場合、最も簡単な方法は、通常の ScrollView レイアウトの代わりに NestedScrollView コントロールを使用することです。
アクティビティのレイアウト:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout\_width="match\_parent"
android:layout\_height="match\_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<LinearLayout
android:layout\_width="match\_parent"
android:layout_height="56dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="56dp"
android:layout_height="56dp"
android:orientation="horizontal"
android:gravity="center">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="16dp"
android:layout\_height="match\_parent"
android:src="@drawable/vector\_arrow\_back"
android:scaleType="fitCenter"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="56dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatTextView
android:layout\_width="wrap\_content"
android:layout\_height="wrap\_content"
android:textStyle="bold"
android:text="弹窗样例"
android:textColor="@color/black"
android:textSize="16sp"
app:autoSizeMaxTextSize="16sp"
app:autoSizeMinTextSize="8dp"
app:autoSizeTextType="uniform"
android:maxLines="1"/>
</LinearLayout>
<LinearLayout
android:layout_width="56dp"
android:layout_height="56dp" />
</LinearLayout>
<androidx.appcompat.widget.AppCompatImageView
android:layout\_width="wrap\_content"
android:layout\_height="wrap\_content"
android:src="@mipmap/ic\_play\_demo"
android:scaleType="center"/>
<LinearLayout
android:layout\_width="match\_parent"
android:layout_height="56dp"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="0dp"
android:layout_height="56dp"
android:layout_weight="1"
android:src="@mipmap/ic\_top\_up"
android:scaleType= "fitCenter"/>
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="0dp"
android:layout_height="56dp"
android:layout_weight="1"
android:src="@mipmap/ic_transfer"
android:scaleType= "fitCenter"/>
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="0dp"
android:layout_height="56dp"
android:layout_weight="1"
android:src="@mipmap/ic_withdraw"
android:scaleType= "fitCenter"/>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/vMore"
android:layout_width="0dp"
android:layout_height="56dp"
android:layout_weight="1"
android:src="@mipmap/ic_more"
android:scaleType= "fitCenter"/>
</LinearLayout>
<LinearLayout
android:id="@+id/vllSize"
android:layout\_width="match\_parent"
android:layout\_height="match\_parent"
android:background="@color/white"
android:orientation="vertical"/>
</LinearLayout>
Activity に呼び出しを実装するコードもあります。
class MainActivity : AppCompatActivity() {
private var dialogHeight : Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
// 获取dialog的高度
dialogHeight = vllSize.measuredHeight
// 获取dialog的高度
Log.d( "MainActivity" ,"height = $dialogHeight")
}
override fun onResume() {
super.onResume()
vMore.setOnClickListener {
val dialog = DialogMore().newInstance()
.setDialogHeight(dialogHeight)
val ft: FragmentTransaction =
supportFragmentManager.beginTransaction()
ft.setTransition(FragmentTransaction.TRANSIT\_FRAGMENT\_FADE)
dialog.show(ft, "DialogMore")
}
}
}
vllSize コントロール (残りの下部) の高さを測定することで、最初のポップアップ ウィンドウの高さをこれに設定できます。もちろん、高さはユーザーが設定できます。
Dialog 実装コードでは次のようになります。
override fun onStart() {
super.onStart()
//拿到系统的 bottom_sheet
val bottomSheetDialog = (dialog as BottomSheetDialog?)!!
val view =
bottomSheetDialog.delegate.findViewById<FrameLayout>(com.google.android.material.R.id.design\_bottom\_sheet)!!
val behavior = BottomSheetBehavior.from(view)
//设置弹出高度
behavior.peekHeight = height
view.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
behavior.isHideable = false
}
view.layoutParams.height ポップアップ ウィンドウを画面全体にプルする 2 回目の時間を設定します
この記事で実装されたポップアップ ウィンドウは、ポップアップ ウィンドウを閉じるためのスライドを禁止しているため、下にスライドしません。コードは、Dialog 実装の属性コントロールです。記述されていない場合、デフォルトは true で、下にスライドしてポップアップ ウィンドウを閉じます。False は、このメソッドがポップアップ ウィンドウを閉じることが禁止されていることを意味します。
behavior.isHideable = false
最終的な効果:
著者: Ru Jiayi
元アドレス