1. 程式人生 > >DialogFragment或者Dialog在某些機型上寬高設定無效或者不適配問題的解決

DialogFragment或者Dialog在某些機型上寬高設定無效或者不適配問題的解決

Dialog可以說是一個專案中的必用控制元件了,但是既然Google推薦用DialogFragment來替代Dialog,那我們就改用DialogFragment吧,話不多說,寫一個最簡單常見的螢幕中間彈出的DialogFragment,下面是java程式碼:

public class CenterTipDialogFragment extends DialogFragment {
    @BindView(R.id.tv_title)
    TextView tvTitle;
    @BindView(R.id.tv_content)
    TextView tvContent;
    @BindView
(R.id.tv_left) TextView tvLeft; @BindView(R.id.tv_right) TextView tvRight; private Unbinder unbinder; private OnClickListener mOnClickListener; private String mTitle; private String mContent; private String mLeftText; private String mRightText; private View mContentView; public
interface OnClickListener { void onLeftBtnClick(); void onRightBtnClick(); } public static CenterTipDialogFragment newInstance(String title,String content,String leftText,String rightText){ CenterTipDialogFragment fragment = new CenterTipDialogFragment(); Bundle bundle = new
Bundle(); bundle.putString("title", title); bundle.putString("content", content); bundle.putString("leftText", leftText); bundle.putString("rightText", rightText); fragment.setArguments(bundle); return fragment; } public CenterTipDialogFragment setClickListener(OnClickListener listener){ mOnClickListener = listener; return this; } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { mContentView = inflater.inflate(R.layout.dlg_center_tip, container, true); unbinder = ButterKnife.bind(this, view); return mContentView; } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams(); layoutParams.width = (int) (getResources().getDisplayMetrics().widthPixels * 0.8); initData(); } private void initData() { Bundle bundle = getArguments(); if (bundle != null){ mTitle = bundle.getString("title"); mContent = bundle.getString("content"); mLeftText = bundle.getString("leftText"); mRightText = bundle.getString("rightText"); } if (TextUtils.isEmpty(mTitle)) { tvTitle.setVisibility(View.GONE); } else { tvTitle.setVisibility(View.VISIBLE); tvTitle.setText(mTitle); } if (TextUtils.isEmpty(mContent)) { tvContent.setVisibility(View.GONE); } else { tvContent.setVisibility(View.VISIBLE); tvContent.setText(mContent); } if (TextUtils.isEmpty(mLeftText)) { tvLeft.setVisibility(View.GONE); } else { tvLeft.setVisibility(View.VISIBLE); tvLeft.setText(mLeftText); } if (TextUtils.isEmpty(mRightText)) { tvRight.setVisibility(View.GONE); } else { tvRight.setVisibility(View.VISIBLE); tvRight.setText(mRightText); } tvLeft.setOnClickListener(v -> { if (mOnClickListener != null) { mOnClickListener.onLeftBtnClick(); CenterTipDialogFragment.this.dismiss(); } }); tvRight.setOnClickListener(v -> { if (mOnClickListener != null) { mOnClickListener.onRightBtnClick(); CenterTipDialogFragment.this.dismiss(); } }); } @Override public void onDestroy() { unbinder.unbind(); super.onDestroy(); } }

然後是xml檔案:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/ll_main"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/bg_radius_white"
    android:divider="@drawable/horizontal_grey_line"
    android:orientation="vertical"
    android:showDividers="middle">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:gravity="center_horizontal"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="30dp"
            android:textColor="@color/color_222222"
            android:textSize="16sp"
            android:textStyle="bold"
            tools:text="稽核未通過" />

        <TextView
            android:id="@+id/tv_content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="40dp"
            android:textColor="@color/color_222222"
            android:textSize="16sp"
            tools:text="圖片不清晰,稽核未通過" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:divider="@drawable/vertical_grey_line"
        android:orientation="horizontal"
        android:showDividers="middle">

        <TextView
            android:id="@+id/tv_left"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:paddingVertical="13dp"
            android:textColor="@color/color_037CFF"
            android:textSize="14sp"
            tools:text="取消" />

        <TextView
            android:id="@+id/tv_right"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:paddingVertical="13dp"
            android:textColor="@color/color_037CFF"
            android:textSize="14sp"
            tools:text="重新認證" />
    </LinearLayout>

</LinearLayout>

程式碼很簡單,和寫fragment幾乎一樣,DialogFragment也是繼承的Fragment,只不過加了Dialog的一些特性。執行程式碼,效果如下圖:這裡寫圖片描述
嗯,是不是很簡單?但是,當我換個手機執行,馬上出現問題,換成vivo手機執行如下圖:這裡寫圖片描述
What?上面多出來的部分和四個角的詭異圓角是什麼鬼?馬上換成Dialog試了一下,結果還是這樣。然後我開始懷疑是我佈局檔案有問題,可能vivo系統的Dialog不能自適應寬高,那麼就給佈局檔案固定寬高,試了好幾種寬高值還是沒解決,而且如果佈局檔案寫死了寬高,那麼如果標題或者內容字數多了就顯示不下了,所以不能寫死。因為對Dialog比DialogFragment熟悉,所以就開始現在Dialog中嘗試解決,首先給Dialog加一個自定義的透明背景style,

<style name="TransparentDialog" parent="@android:style/Theme.Dialog">
        <!-- 背景透明 -->
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowContentOverlay">@null</item>
        <!-- 浮於Activity之上 -->
        <item name="android:windowIsFloating">true</item>
        <!-- 邊框 -->
        <item name="android:windowFrame">@null</item>
        <!-- Dialog以外的區域模糊效果 -->
        <item name="android:backgroundDimEnabled">true</item>
        <!-- 無標題 -->
        <item name="android:windowNoTitle">true</item>
        <!-- 半透明 -->
        <item name="android:windowIsTranslucent">true</item>
    </style>

執行,無效!程式碼中重新設定contentView的寬高:

ViewGroup.LayoutParams layoutParams = contentView.getLayoutParams();
        layoutParams.width = (int) (activity.getResources().getDisplayMetrics().widthPixels * 0.8);
        layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
        contentView.setLayoutParams(layoutParams);

執行,依然無效!靜下心來好好分析吧,看現象好像是我的contentView加入到Dialog中的時候,Dialog的最根佈局針對contentView做了處理,導致我後面重新對contentView設定layoutParams無效,那把這段程式碼放到setContentView之前試試,結果會崩潰,因為contentView.getLayoutParams()會返回null。那自己new一個layoutParams,

ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams((int) (activity.getResources().getDisplayMetrics().widthPixels * 0.8),
                ViewGroup.LayoutParams.WRAP_CONTENT);
        contentView.setLayoutParams(layoutParams);
        dialog.setContentView(contentView);

然後效果如下:這裡寫圖片描述
嗯,終於有所改變,看來快解決了,加油。看目前這個現象,既然對contentView設定layoutParams不行,那就對子控制元件設定,我先是對xml檔案的根佈局,就是上面xml裡的最外層的Linearlayout設定layoutParams,無效!這樣應該和對contentView設定是一樣的。那就在外面再包一層FramLayout,執行,正常了!然後再試試之前本來就顯示正常的手機,也是好的。到此,問題解決!然後把解決思路用回到DialogFragment,同樣問題解決了。Dialog的程式碼就不貼了,下面是DialogFragment的完整的程式碼:

public class CenterTipDialogFragment extends DialogFragment {
    @BindView(R.id.tv_title)
    TextView tvTitle;
    @BindView(R.id.tv_content)
    TextView tvContent;
    @BindView(R.id.tv_left)
    TextView tvLeft;
    @BindView(R.id.tv_right)
    TextView tvRight;
    @BindView(R.id.ll_main)
    LinearLayout mRootLayout;

    private Unbinder unbinder;
    private OnClickListener mOnClickListener;
    private String mTitle;
    private String mContent;
    private String mLeftText;
    private String mRightText;

    public interface OnClickListener {
        void onLeftBtnClick();

        void onRightBtnClick();
    }

    public static CenterTipDialogFragment newInstance(String title,String content,String leftText,String rightText){
        CenterTipDialogFragment fragment = new CenterTipDialogFragment();
        Bundle bundle = new Bundle();
        bundle.putString("title", title);
        bundle.putString("content", content);
        bundle.putString("leftText", leftText);
        bundle.putString("rightText", rightText);
        fragment.setArguments(bundle);
        return fragment;
    }

    public CenterTipDialogFragment setClickListener(OnClickListener listener){
        mOnClickListener = listener;
        return this;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.dlg_center_tip, container, true);
        //下面這兩行程式碼是關鍵,和Dialog設定背景透明和無標題的自定義style是同樣的效果
        getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
        getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        unbinder = ButterKnife.bind(this, view);
        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        //這裡也是關鍵,mRootLayout是xml檔案中倒數第二層的layout,而非最外層的layout
        ViewGroup.LayoutParams layoutParams = mRootLayout.getLayoutParams();
        layoutParams.width = (int) (getResources().getDisplayMetrics().widthPixels * 0.8);
        initData();
    }

    private void initData() {
        Bundle bundle = getArguments();
        if (bundle != null){
            mTitle = bundle.getString("title");
            mContent = bundle.getString("content");
            mLeftText = bundle.getString("leftText");
            mRightText = bundle.getString("rightText");
        }
        if (TextUtils.isEmpty(mTitle)) {
            tvTitle.setVisibility(View.GONE);
        } else {
            tvTitle.setVisibility(View.VISIBLE);
            tvTitle.setText(mTitle);
        }

        if (TextUtils.isEmpty(mContent)) {
            tvContent.setVisibility(View.GONE);
        } else {
            tvContent.setVisibility(View.VISIBLE);
            tvContent.setText(mContent);
        }

        if (TextUtils.isEmpty(mLeftText)) {
            tvLeft.setVisibility(View.GONE);
        } else {
            tvLeft.setVisibility(View.VISIBLE);
            tvLeft.setText(mLeftText);
        }

        if (TextUtils.isEmpty(mRightText)) {
            tvRight.setVisibility(View.GONE);
        } else {
            tvRight.setVisibility(View.VISIBLE);
            tvRight.setText(mRightText);
        }

        tvLeft.setOnClickListener(v -> {
            if (mOnClickListener != null) {
                mOnClickListener.onLeftBtnClick();
                CenterTipDialogFragment.this.dismiss();
            }
        });

        tvRight.setOnClickListener(v -> {
            if (mOnClickListener != null) {
                mOnClickListener.onRightBtnClick();
                CenterTipDialogFragment.this.dismiss();
            }
        });
    }

    @Override
    public void onDestroy() {
        unbinder.unbind();
        super.onDestroy();
    }
}

xml檔案:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/bg_radius_white">

    <LinearLayout
        android:id="@+id/ll_main"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:divider="@drawable/horizontal_grey_line"
        android:orientation="vertical"
        android:showDividers="middle">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="30dp"
            android:gravity="center_horizontal"
            android:orientation="vertical">

            <TextView
                android:id="@+id/tv_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginBottom="30dp"
                android:textColor="@color/color_222222"
                android:textSize="16sp"
                android:textStyle="bold"
                tools:text="稽核未通過" />

            <TextView
                android:id="@+id/tv_content"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginBottom="40dp"
                android:textColor="@color/color_222222"
                android:textSize="16sp"
                tools:text="圖片不清晰,稽核未通過" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:divider="@drawable/vertical_grey_line"
            android:orientation="horizontal"
            android:showDividers="middle">

            <TextView
                android:id="@+id/tv_left"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:gravity="center"
                android:paddingVertical="13dp"
                android:textColor="@color/color_037CFF"
                android:textSize="14sp"
                tools:text="取消" />

            <TextView
                android:id="@+id/tv_right"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:gravity="center"
                android:paddingVertical="13dp"
                android:textColor="@color/color_037CFF"
                android:textSize="14sp"
                tools:text="重新認證" />
        </LinearLayout>


    </LinearLayout>
</FrameLayout>

最後吐槽一下,android適配確實是件讓人頭疼的事。