Android自定義Dialog的2種常見(jiàn)方法
前言
大多數(shù)中,使用系統(tǒng)內(nèi)置的dialog并不能滿足UE的設(shè)計(jì)需要
方式一:繼承DialogFragment,也是官方推薦的方式
通常我們只需要關(guān)注三個(gè)回調(diào)方法:
- onCreateDialog:創(chuàng)建一個(gè)dialog外殼
- onCreateView:給dialog外殼填充自己想要的樣式布局
- onViewCreated:這里面給布局的view進(jìn)行初始化操作,可以設(shè)置一些監(jiān)聽(tīng)器等等
事例
自定義布局文件:隨便寫(xiě)一個(gè)
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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:id="@+id/threat_call_rootView" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/dialog_white_big_corner_roundrect_bg"> <LinearLayout android:id="@+id/threat_call_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/dialog_white_big_corner_roundrect_bg" android:orientation="vertical" android:paddingLeft="32dp" android:paddingTop="48dp" android:paddingRight="32dp" android:paddingBottom="48dp"> <TextView android:id="@+id/threat_call_number" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="標(biāo)題" android:textColor="@color/black" android:textSize="20sp" android:textStyle="bold" /> <TextView android:id="@+id/threat_call_desc" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:lineSpacingExtra="3sp" android:text="正文" android:textColor="@color/black" android:textSize="14sp" /> <EditText android:id="@+id/threat_call_edittext" android:layout_width="match_parent" android:layout_height="48dp" android:layout_marginTop="16dp" android:width="100dp" android:background="@drawable/sip_threat_call_dialog_edittext_stroke"http://給editText加個(gè)外邊框 android:hint=" (optional)" android:lineSpacingExtra="3sp" android:maxLength="255" android:minLines="1" android:paddingLeft="5dp"http://這個(gè)屬性的一個(gè)妙用可以改變光標(biāo)的起始位置,不然光標(biāo)有可能看不到 android:text="" android:textCursorDrawable="@null" android:textSize="14sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/threat_call_block_btn" android:layout_width="match_parent" android:layout_height="48dp" android:layout_marginTop="16dp" android:background="@drawable/sip_threat_call_dialog_btn_bg" android:gravity="center" android:text="BLOCK" android:textStyle="bold" /> <Button android:id="@+id/threat_call_cancel_btn" android:layout_width="match_parent" android:layout_height="48dp" android:layout_marginTop="1dp" android:background="@drawable/sip_threat_call_dialog_btn_bg" android:gravity="center" android:text="CANCEL" android:textStyle="bold" /> </LinearLayout> </RelativeLayout>
selfFragment類(lèi):
package com.example.hellojni; import android.animation.ObjectAnimator; import android.annotation.SuppressLint; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.DialogFragment; public class selfDialogFragment extends DialogFragment { View container; @NonNull @Override public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { return new Dialog(getContext(),R.style.bottom_dialog); // return super.onCreateDialog(savedInstanceState);//不采用系統(tǒng)默認(rèn)的dialog樣式,自定義dialog主題 } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { Window window = getDialog().getWindow(); window.setLayout(WindowManager.LayoutParams.MATCH_PARENT,WindowManager.LayoutParams.WRAP_CONTENT); window.setGravity(Gravity.CENTER);//設(shè)置dialog位置處于中央 if(!iPaid(getContext())){ window.getDecorView().setMinimumWidth(getResources().getDisplayMetrics().widthPixels);//這個(gè)設(shè)置的目的是為了讓dialog橫向?qū)挾仁浅錆M屏幕的 } // window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);//本來(lái)想解決dialog打開(kāi)軟鍵盤(pán)后,彈窗跟著往上走的效果,效果確實(shí)有,不過(guò)依然沒(méi)有解決我的問(wèn)題,下面會(huì)詳解。 return inflater.inflate(R.layout.dialog_block_reason,container,false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); View dialogViewContent = view.findViewById(R.id.block_number_container); EditText editText = view.findViewById(R.id.optional_block_number); container = view.findViewById(R.id.block_number_container); editText.requestFocus(); InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); dialogViewContent.setOnTouchListener(new View.OnTouchListener() { @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouch(View v, MotionEvent event) { //強(qiáng)制收起軟件盤(pán)的方式: InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(editText.getWindowToken(),0); return false; } }); view.findViewById(R.id.cancel_btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { dismissAllowingStateLoss(); hideSoftInputAndDissmissDialog(); } }); private void hideSoftInputAndDissmissDialog() { dismissAllowingStateLoss(); if (getActivity() != null) {//為了解決dialog彈出軟鍵盤(pán)退出界面后軟鍵盤(pán)依然存在的問(wèn)題 getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); } } @Override public void onStart() { super.onStart(); } //判斷是否為Pad的方法,通過(guò)計(jì)算屏幕對(duì)角線長(zhǎng)度 private boolean isPad(Context context) { WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); DisplayMetrics dm = new DisplayMetrics(); display.getMetrics(dm); double x = Math.pow(dm.widthPixels / dm.xdpi, 2); double y = Math.pow(dm.heightPixels / dm.ydpi, 2); double screenInches = Math.sqrt(x + y); // 屏幕尺寸 return screenInches >= 7.0; } }
- 坑點(diǎn)講解
- 當(dāng)dialog有editText的時(shí)候,如果你的dialog主題中的
<item name="android:windowIsFloating">false</item>
指定為false的話,即便加上了 window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
也不行 效果如下:可以清楚的看到,軟鍵盤(pán)還是擋住了兩個(gè)按鈕
android:windowIsFloating
設(shè)為true時(shí),效果如下:
不過(guò)中間多出來(lái)的那塊我也不知道受什么因素影響的,目前這個(gè)樣式還能湊活用吧
- 默認(rèn)的dialog并非是橫向充滿屏幕的
我這邊用了使用了window.getDecorView().setMinimumWidth(getResources().getDisplayMetrics().widthPixels);
生效了,有的博客說(shuō)是使用 window.getDecorView().setPadding(0,0,0,0)
或者主題中有個(gè)屬性android:windowFullscree
,不過(guò)這兩個(gè)我試過(guò)都貌似都沒(méi)有什么效果
- 當(dāng)打開(kāi)軟鍵盤(pán),然后點(diǎn)擊空白處的時(shí)候,dialog消失,但是軟鍵盤(pán)卻還是打開(kāi)著。
這個(gè)點(diǎn)我使用了getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
解決了,這句話等同于在展示dialog的activity中androidMenifests文件中設(shè)置 andorid:windowSoftInputMode = stateAlwaysHidden
,而僅僅設(shè)置成stateHidden是不夠的,具體這兩個(gè)參數(shù)的詳細(xì)區(qū)別,官方文檔說(shuō)的也很含糊,反正我沒(méi)讀懂。
我比較認(rèn)同這篇文章的看法: Android 進(jìn)入Activity時(shí)如何禁止彈出軟鍵盤(pán)輸入法
- 默認(rèn)的dialog出場(chǎng)以及退場(chǎng)動(dòng)畫(huà)是采用了縮放以及透明度,可以在主題中自定義出場(chǎng)動(dòng)畫(huà)
enter動(dòng)畫(huà):
<?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:fromYDelta="100%p" android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:toYDelta="50%p" android:duration="200"> </translate>
exit動(dòng)畫(huà):
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false" > <scale android:fromXScale="1.0" android:toXScale="0.9" android:fromYScale="1.0" android:toYScale="0.9" android:pivotX="50%" android:pivotY="50%" android:interpolator="@android:anim/decelerate_interpolator" android:duration="150" /> <alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:interpolator="@android:anim/decelerate_interpolator" android:duration="150"/> </set>
方式二:直接繼承Dialog類(lèi)或者AppCompatDialog類(lèi)
通常只需要關(guān)注onCreate
方法,在該方法中,一般需要做如下幾個(gè)事情:
- 通過(guò)
setContentView
將自定義的布局填充到dialog中去 - 初始化布局中的子view,并設(shè)置監(jiān)聽(tīng)器,事件響應(yīng)等
- 初始化window相關(guān)的屬性,比如設(shè)置window的寬度和高度,以及window所顯示的位置等等
在構(gòu)造函數(shù)中設(shè)置想要的主題:這里提供兩種比較常用的主題
<!--對(duì)話框會(huì)在屏幕中間顯示--> <style name="dialog_theme_center_dispay" parent="@android:style/Theme.Dialog"> <item name="android:windowFrame">@null</item><!-- 設(shè)置dialog空白背景--> <item name="android:windowIsFloating">true</item> <!-- dialog是否懸浮,當(dāng)有軟鍵盤(pán)的時(shí)候會(huì)被頂上去--> <item name="android:windowIsTranslucent">false</item> <!-- dialog是否半透明 --> <item name="android:windowMinWidthMinor">100%</item> <!-- dialog橫向?qū)挾瘸錆M整個(gè)屏幕 --> <item name="android:windowNoTitle">true</item><!-- dialog是否有標(biāo)題 --> <item name="android:windowBackground">@color/transparent</item><!-- dialog背景是透明的 --> <item name="android:background">@color/transparent</item> <item name="android:backgroundDimEnabled">true</item> <item name="android:windowSoftInputMode">stateHidden|adjustResize</item> </style> <!--對(duì)話框會(huì)從底部彈出--> <style name="dialog_theme_bottom2top"> <item name="android:windowFrame">@null</item> <item name="android:windowIsFloating">true</item> <item name="android:windowIsTranslucent">false</item> <item name="android:windowNoTitle">true</item> <item name="android:windowBackground">@color/transparent</item> <item name="android:backgroundDimEnabled">true</item> <!--是否允許對(duì)話框的背景變暗:如果允許背景就變暗了。--> <item name="android:windowMinWidthMinor">100%</item><!--寬度鋪滿全屏--> <item name="android:windowCloseOnTouchOutside">true</item><!--點(diǎn)擊陰影的地方是否可以關(guān)閉對(duì)話框--> <item name="android:windowAnimationStyle">@style/dialog_anim_bottom2top</item><!--對(duì)話框動(dòng)畫(huà)--> <item name="android:windowSoftInputMode">stateHidden|adjustResize</item> </style> <!--[對(duì)話框動(dòng)畫(huà)]對(duì)話框會(huì)從底部彈出--> <style name="dialog_anim_bottom2top" parent="@android:style/Animation"> <item name="android:windowEnterAnimation">@anim/bottom_in</item> <item name="android:windowExitAnimation">@anim/bottom_out</item> </style>
bottom_in:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:duration="300" android:fromYDelta="100%p" android:toYDelta="0" /> </set>
bottom_out:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:duration="200" android:fromYDelta="0" android:toYDelta="50%p" /> <alpha android:duration="200" android:fromAlpha="1.0" android:toAlpha="0.0" /> </set>
更新
辨別當(dāng)前設(shè)備是否是平板的方法通常有兩種:
public static boolean isLargeScreen(Context context) { Configuration config = context.getResources().getConfiguration(); int size = config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK; return (size >= Configuration.SCREENLAYOUT_SIZE_LARGE); }
public static boolean isPad(Context context) { WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); DisplayMetrics dm = new DisplayMetrics(); display.getMetrics(dm); double x = Math.pow(dm.widthPixels / dm.xdpi, 2); double y = Math.pow(dm.heightPixels / dm.ydpi, 2); double screenInches = Math.sqrt(x + y); // 屏幕尺寸 return screenInches >= 7.0; }
到此這篇關(guān)于Android自定義Dialog的2種常見(jiàn)方法的文章就介紹到這了,更多相關(guān)Android自定義Dialog內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Android自定義Dialog框樣式
- Android自定義Dialog原理實(shí)例解析
- Android 自定義加載動(dòng)畫(huà)Dialog彈窗效果的示例代碼
- Android自定義底部彈出框ButtomDialog
- android自定義Dialog彈框和背景陰影顯示效果
- Android自定義Dialog實(shí)現(xiàn)通用圓角對(duì)話框
- Android自定義dialog 自下往上彈出的實(shí)例代碼
- Android 自定義Dialog去除title導(dǎo)航欄的解決方法
- Android自定義Dialog實(shí)現(xiàn)加載對(duì)話框效果
- Android編程自定義AlertDialog樣式的方法詳解
- 解決Android中自定義DialogFragment解決寬度和高度問(wèn)題
- Android 自定義 Dialog 實(shí)現(xiàn)列表 單選,多選,搜索功能
相關(guān)文章
Android中RecyclerView點(diǎn)擊Item設(shè)置事件
這篇文章主要介紹了Android中RecyclerView點(diǎn)擊Item設(shè)置事件的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-07-07Android?8.0實(shí)現(xiàn)藍(lán)牙遙控器自動(dòng)配對(duì)
這篇文章主要為大家詳細(xì)介紹了Android?8.0實(shí)現(xiàn)藍(lán)牙遙控器自動(dòng)配對(duì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08Android中ListView分頁(yè)加載數(shù)據(jù)功能實(shí)現(xiàn)
本篇文章主要介紹了Android中ListView分頁(yè)加載數(shù)據(jù)功能實(shí)現(xiàn),具有一定的參考價(jià)值,有需要的可以了解一下。2016-11-11Android開(kāi)發(fā)實(shí)現(xiàn)實(shí)時(shí)檢測(cè)藍(lán)牙連接狀態(tài)的方法【附源碼下載】
這篇文章主要介紹了Android開(kāi)發(fā)實(shí)現(xiàn)實(shí)時(shí)檢測(cè)藍(lán)牙連接狀態(tài)的方法,涉及Android針對(duì)藍(lán)牙連接狀態(tài)的監(jiān)測(cè)操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-11-11Kotlin引用其他xml的view對(duì)象過(guò)程詳解
這篇文章主要介紹了Kotlin中如何引用其他xml中的view對(duì)象,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2023-02-02Android實(shí)現(xiàn)使用微信登錄第三方APP的方法
這篇文章主要介紹了Android實(shí)現(xiàn)使用微信登錄第三方APP的方法,結(jié)合實(shí)例形式分析了Android微信登錄APP的操作步驟與具體功能實(shí)現(xiàn)技巧,需要的朋友可以參考下2016-11-11新版Flutter集成到已有Android項(xiàng)目的實(shí)現(xiàn)
這篇文章主要介紹了新版Flutter集成到已有Android項(xiàng)目的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03Android編程實(shí)現(xiàn)Listview點(diǎn)擊展開(kāi)和隱藏的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)Listview點(diǎn)擊展開(kāi)和隱藏的方法,涉及Android中Listview的響應(yīng)點(diǎn)擊與樣式變換相關(guān)操作技巧,需要的朋友可以參考下2015-12-12