1. 程式人生 > >Android 自定義DialogFragment 以及設定寬高

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