Android 自定義DialogFragment 以及設定寬高
DialogFragment 的特點是具有dialog 的 效果,同時又可以擁有Fragment 的生命週期,因此我們可以像管理Fragment 一樣管理DialogFragment 。在 Android 中我們已經Dialog 類了,為什麼還要增加一個DialogFragment 。在使用過程中DialogFragment 有事什麼樣子的呢,我們通過一個demo 來介紹。
設計一個從底部彈出的彈出框,同時 彈出框中的包汗tab頁。那麼我們需要在彈出框佈局中加入 Viewpager+ Fragment 的設計。對於複雜的 dialog 我們可以用 DialogFragment 來做。
效果如圖:
fragment 佈局檔案
<?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" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:id="@+id/contentView" android:layout_width="match_parent" android:layout_height="300dp" android:orientation="vertical" android:layout_marginLeft="10dp" android:layout_marginBottom="10dp" android:layout_marginRight="10dp" android:layout_marginTop="150dp" android:background="@drawable/bg_list" android:layout_alignParentBottom="true" > <com.ogaclejapan.smarttablayout.SmartTabLayout android:id="@+id/vp_tab" android:layout_width="match_parent" android:layout_height="50dp" android:layout_gravity="center" android:background="@color/transparent" app:stl_indicatorAlwaysInCenter="false" app:stl_indicatorWithoutPadding="false" app:stl_indicatorInFront="false" app:stl_indicatorInterpolation="linear" app:stl_indicatorGravity="bottom" app:stl_indicatorColor="@color/colorAccent" app:stl_indicatorThickness="2dp" app:stl_indicatorWidth="auto" app:stl_indicatorCornerRadius="1px" app:stl_overlineColor="#4D000000" app:stl_overlineThickness="0dp" app:stl_underlineColor="@color/line" app:stl_underlineThickness="0dp" app:stl_dividerColor="@color/line" app:stl_dividerThickness="0dp" app:stl_defaultTabBackground="@android:color/transparent" app:stl_defaultTabTextAllCaps="false" app:stl_defaultTabTextColor="#ffffff" app:stl_defaultTabTextSize="12sp" app:stl_defaultTabTextMinWidth="0dp" app:stl_distributeEvenly="true" app:stl_clickable="true" app:stl_titleOffset="24dp" app:stl_drawDecorationAfterTab="false" /> <TextView android:layout_width="match_parent" android:layout_height="1px" android:background="@color/line" /> <android.support.v4.view.ViewPager android:id="@+id/vp" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> </RelativeLayout>
fragment Java檔案
/** * @author by nate_fu on 2018/9/13. * @version vision 1.0 * @Email: [email protected] */ public class MyDialogFragment extends DialogFragment { private View view; private ViewPager viewPager; private SmartTabLayout vpTab; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setStyle(DialogFragment.STYLE_NO_TITLE, R.style.CustomDialog); } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { view = inflater.inflate(R.layout.fragment_dialog,container,false); initViewpage(); return view; } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); Window window = getDialog().getWindow(); getDialog().setCanceledOnTouchOutside(true); window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); window.setWindowAnimations(R.style.dialogWindowAnim); WindowManager.LayoutParams wlp = window.getAttributes(); wlp.dimAmount=0f; wlp.width = WindowManager.LayoutParams.MATCH_PARENT ; wlp.height =WindowManager.LayoutParams.MATCH_PARENT ; window.setAttributes(wlp); } private void initViewpage(){ FragmentPagerItemAdapter adapter = new FragmentPagerItemAdapter( getChildFragmentManager(), FragmentPagerItems.with(getActivity()) .add("XX",InfoFragment.class) .add("XX",InfoFragment.class) .add("XX",InfoFragment.class) .add("XX",InfoFragment.class) .add("XX",InfoFragment.class) .create()); viewPager = (ViewPager)view.findViewById(R.id.vp); viewPager.setAdapter(adapter); vpTab =(SmartTabLayout)view.findViewById(R.id.vp_tab); vpTab.setViewPager( viewPager); } @Override public void show(FragmentManager manager, String tag) { super.show(manager, tag); } }
在MyDialogFragment 類中。我們在onCreate()方法中 執行了setStyle()方法 來設定dialog 的樣式。為什麼要在這裡執行這個方法。我們可以從DialogFragment 的原始碼中找找原因
setStyle(DialogFragment.STYLE_NO_TITLE, R.style.CustomDialog);
@Override
public LayoutInflater onGetLayoutInflater(Bundle savedInstanceState) {
if (!mShowsDialog) {
return super.onGetLayoutInflater(savedInstanceState);
}
mDialog = onCreateDialog(savedInstanceState);
if (mDialog != null) {
setupDialog(mDialog, mStyle);
return (LayoutInflater) mDialog.getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
}
return (LayoutInflater) mHost.getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
}
在 DialogFragmet 類中有一個 onGetLayoutInflater()方法。其中 建立了Dialog 物件,同時 在setupDiaglog中設定了 style
所以我們必須在 onGetLayoutInflater()方法前設定style 。
f.mContainer = container;
f.mView = f.performCreateView(f.performGetLayoutInflater(
f.mSavedFragmentState), container, f.mSavedFragmentState);
這是在FragmentManager 類中找到的程式碼,可以看到 getLayoutInflater 在 CreateView 之前,所以我們不能再 onCreateView()中設定是style 而在Fragment的生命週期 中 onCreate()在 onCreateView()之前呼叫。
接下來我們就是要設定我們要的dialog 的寬高 了。預設建立的 dialog 會在中間位置,兩邊會留邊。而我們習慣在 onCreateView() 中
Window window = getDialog().getWindow();
getDialog().setCanceledOnTouchOutside(true);
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
window.setWindowAnimations(R.style.dialogWindowAnim);
WindowManager.LayoutParams wlp = window.getAttributes();
wlp.dimAmount=0f;
wlp.width = WindowManager.LayoutParams.MATCH_PARENT ;
wlp.height =WindowManager.LayoutParams.MATCH_PARENT ;
window.setAttributes(wlp);
直接給window 設定寬高。因為在我們自定義 Dialog 是 ,new Dialog()之後我們就是這麼操作的,發現在Dialog 的時候沒什麼問題,可是到了這裡卻沒有效果了,這是為什麼呢。我們還是繼續去原始碼中檢視
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (!mShowsDialog) {
return;
}
View view = getView();
if (view != null) {
if (view.getParent() != null) {
throw new IllegalStateException(
"DialogFragment can not be attached to a container view");
}
mDialog.setContentView(view);
}
在DialogFragment 中的 onActivityCreated 中 我們發現, mDialog.setContentView 這行程式碼,我們知道Android 中實現window 這個類的就是PhoneWindow 類。而 我們平時在onCreate 方法中呼叫的setContentView 最終呼叫的是 PhoneWindow 中的setContentView 方法
PhoneWindow.java
@Override
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor();
} else {
mContentParent.removeAllViews();
}
mLayoutInflater.inflate(layoutResID, mContentParent);
final Callback cb = getCallback();
if (cb != null) {
cb.onContentChanged();
}
}
我們看到了 其中執行了installDecor();
private void installDecor() {
mForceDecorInstall = false;
if (mDecor == null) {
mDecor = generateDecor(-1);
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
} else {
mDecor.setWindow(this);
}
}
這裡我們看到當mDecor為null 的時候 則呼叫generateDecor方法完成DecorView的初始化。
而我們在結合Dialog 類來看。
@Override
public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
if (mDecor != null) {
mWindowManager.updateViewLayout(mDecor, params);
}
}
當我們 給window設定Attributes 時候會回撥 onWindowAttributesChanged 方法,而 在這個方法中,如果 mDecor 為null 的話是不會update我們的引數的。所以從上面我們知道 在 DialogFragment 中,dialog 視窗 被建立是在 onActivityCreate中,在此DecorView才被例項化。而我們要設定寬高的引數,必須在 DecorView例項化之後,不然是沒有效果的。
以上是我的分析,如果有其他見解歡迎留言討論。
demo 下載地址
相關推薦
Android 自定義DialogFragment 以及設定寬高
DialogFragment 的特點是具有dialog 的 效果,同時又可以擁有Fragment 的生命週期,因此我們可以像管理Fragment 一樣管理DialogFragment 。在 Android 中我們已經Dialog 類了,為什麼還要增加一
Android 自定義view-如何設定TextView drawableLeft 圖片大小?
2017/09/07更新 開發過程中,越發強烈的覺得需要對TextView進一步封裝 1.TextView需要設定背景或者邊框時需要編寫大量的selector,稍微修改一下樣式又得編寫一個新的selector,這個實在不能忍! 2.使用原生TextView
Android 自定義PopupWindow以及引數傳遞與返回
在這篇部落格之前,還寫了一篇關於PopupWindow,那篇主要是關於PopupWindow彈出位置的設定。以及選擇PopupWindow佈局後的監聽。詳情看Android popupwindow 示例程式一。接下來這篇主要是講自定義PopupWindow以及引數傳遞與返
Android 自定義 Dialog 佈局設定高度 wrap_content 無效
以前的一個 Dialog 的自定義佈局的根佈局的寬度是寫死的,高度是 wrap_content 的。後來加了幾行內容後,發現內容總是顯示不全,高度沒有自適應,似乎變成了一個固定高度。根佈局是一個垂直的 LinearLayout,之前的內容比較少,所以沒發現問題。這期在底部添加
android 自定義dialogfragment全屏對話窗體
public class ConfigDialogFragment extends DialogFragment implements View.OnClickListener{ private ImageView force_close; private
Android自定義super以及this的用法問題
Android自定義開發當中的繼承view的時候,我們一般會使用3個建構函式 因為四個引數的建構函式是API21之後才出來的,所以我們暫時都是使用的都是這3種。在我自己學習自定義的過程當中,就在這個建構函式的地方出了問題。將super和this的用法弄錯了。所以自己在這裡記
Android 自定義dialogfragment
在用dialogfragment的時候我們可能會不喜歡系統自帶的黑色邊框, 那怎麼辦呢? dialofragment提供可供修改樣式的方法setStyle(style,R.style.MyTryU
android程式碼構建佈局時設定寬高的單位為畫素(圖解)
android構建佈局時一般通用xml佈局來生成,但有時還是需要程式碼來生成佈局控制元件,以達到不同的效果。以前用過程式碼生成佈局,現在寫個總結,方便新手檢視。 這裡程式碼來生成佈局控制元件設定的寬高的單位為:畫素。 畫素即pixel,簡寫為px,我們平時說的手機的40
Android自定View——可以設定寬高比例的ImageView
public class RatioImageView extends ImageView { /* 優先順序從大到小: mIsWidthFitDrawableSizeRatio mIsHeightFitDrawableSizeRatio mWidthRatio mHeightR
Android 自定義設定圖片模糊度、高斯模糊效果
最近專案中有需要到“毛玻璃”效果,網上找一下,千篇一律。高談闊論扯淡的多,真正有用的沒幾個! 藉助此文,做修改之後,實現效果!我只是個搬運工,在此表示感謝! 淡不多扯,直接上程式碼: MainActivity: public class MainActiv
Android 自定義橫向進度條(可動態設定最大值)
自定義橫向進度條 主佈局檔案中包 含 <LinearLayout android:id="@+id/linearlayout" android:layout_width="match_parent" androi
Android自定義TextView 自定義設定圓角背景色
public class RoundTextView extends TextView { private int mBgColor = 0; private int mCornerSize = 18; public RoundTextView(Context cont
Android--自定義Button的樣式以及動態漸變效果
之前開發使用過自定義樣式的Button,使用挺簡單的,但也很常用,因此總結一下。 1,使用drawable檔案自定義靜態的Button樣式 首先,自定義一個drawable檔
android 自定義Dialog背景透明及顯示位置設定(轉載)
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" a
Android 自定義Notification通知樣式並設定按鈕監聽.
這篇文章主要是記錄一個自定義Notification樣式的學習過程。介面比較簡單,也沒有格外去用心的搭建,只是為了實現自定義效果。 先來看看效果圖,通過Activity中的button點選彈出通知。 現在我們先來看看佈局介面,第一個介面主要就是一個but
android 反射實現自定義toast 自由設定消失時間
先上一張圖,再說話: 在android中,Toast是用來實現簡要資訊展示,與介面無關的一種無可點選操作的懸浮層,它和PopupWindow還有dialog不同,popupWindow和dialog是基於activity,detcorView來展示的,它們顯示的時候
Android自定義View,高仿QQ音樂歌詞滾動控制元件!
最近在以QQ音樂為樣板做一個手機音樂播放器,原始碼下篇博文放出。今天我想聊的是這個QQ音樂播放器中歌詞顯示控制元件的問題,和小夥伴們一起來探討怎麼實現這個歌詞滾動的效果。OK,廢話不多說,先來看看效果圖:好,接下來我們就來看看怎麼實現這樣一個效果。本文主要包括如下幾方面內容:
Android自定義view-打造酷炫的字型滑動高亮控制元件
前言: 相信很多時候開發會遇到類似於音樂歌詞同步,播放到哪句歌詞的哪個詞時會逐漸高亮,這樣的描述還是不夠準確,iPhone的滑動解鎖的那種效果,相信很多人都會熟悉吧。今天,我們的首要任務就是開發一個類似於這種效果的安卓控制元件,以便在以後的專案中直接使用,看起來高大上有木有
整個網路可能最完善的 Android 自定義鍵盤 問題彙總以及解決方案
系統自帶的鍵盤,鍵值太多,不符合客戶的需求,需要自定義鍵盤,如下圖: 分別是字母和數字的鍵盤,感謝很多前輩提供的例子,朋友們可以到這個連結下載資源:前輩android 自定義鍵盤詳解講的非常清楚,我下了他的程式碼,在這基礎上進行修改,
android 自定義寬高比的自定義View
這裡以16:9為例,定好寬,高自適應 public class View_16_9 extends View { public View_16_9(Context context) { super(context); } publ