天天看點

Android中Dialog使用小記

使用dialog除了可以用AlertDialog.Builder方法直接生成,也可以使用DialogFragment的形式來建立。

第一種方式:

    第一種方式有兩種寫法,當dialog對話框中含有edittext等可輸入控件時,需要把builder.create().show()方法寫在setView()方法之後,要不然會出現手機上鍵盤顯示不出來的問題。

例如下面這種代碼實作的對話框,當點選輸入的edittext時,手機上鍵盤顯示不出來,如下:

private void weightClick(float bodyWeight) {
    final AlertDialog alertDialog = new AlertDialog.Builder(SettingActivity.this, R.style.my_dialog).create();
    alertDialog.show();
    if (alertDialog.getWindow() == null) {
        return;
    }
    alertDialog.getWindow().setContentView(R.layout.view_dialog_input);
    TextView msg = (TextView) alertDialog.findViewById(R.id.tv_msg);
    Button cancel = (Button) alertDialog.findViewById(R.id.btn_cancle);
    Button sure = (Button) alertDialog.findViewById(R.id.btn_sure);
    final EditText input = (EditText) alertDialog.findViewById(R.id.input);
    if (msg == null || cancel == null || sure == null || input == null) {
        return;
    }
    msg.setText("設定體重");
    input.setText(String.valueOf(bodyWeight));
    cancel.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            alertDialog.dismiss();
        }
    });
    sure.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            String val = input.getText().toString();
            if (!TextUtils.isEmpty(val) && val.length() > 0) {
                float bodyWeight = Float.parseFloat(val);
                setting.setBodyWeight(bodyWeight);
                if (adapter != null) {
                    adapter.notifyDataSetChanged();
                }
            } else {
                Utils.makeToast(SettingActivity.this, "請輸入正确的參數!");
            }
            alertDialog.dismiss();
        }
    });
}      

其中的style.my_dialog的内容為:

<style name="my_dialog" parent="@android:style/Theme.DeviceDefault.Light.Dialog">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowNoTitle">true</item>
</style>      

R.layout.view_dialog_iput的内容為:

<?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"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="@dimen/item_margin"
    android:layout_marginRight="@dimen/item_margin"
    android:orientation="vertical">

    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:cardCornerRadius="10dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:id="@+id/tv_msg"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:layout_marginBottom="16dp"
                android:layout_marginLeft="@dimen/item_margin"
                android:layout_marginRight="@dimen/item_margin"
                android:layout_marginTop="25dp"
                android:gravity="center"
                android:textColor="@color/fontBlack"
                android:textSize="@dimen/text_size"
                android:textStyle="bold" />

            <EditText
                android:id="@+id/input"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:layout_marginBottom="16dp"
                android:layout_marginLeft="16dp"
                android:layout_marginRight="16dp"
                android:layout_marginTop="5dp"
                android:gravity="center"
                android:background="@drawable/dialog_background"
                android:inputType="numberDecimal"
                android:textColor="@color/fontBlack" />

            <View style="@style/DividingLine" />


            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:orientation="horizontal">

                <Button
                    android:id="@+id/btn_cancle"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@null"
                    android:gravity="center"
                    android:text="取消"
                    android:textColor="#3995fa"
                    android:textSize="@dimen/text_size"
                    android:textStyle="bold" />

                <View
                    android:layout_width="1dp"
                    android:layout_height="match_parent"
                    android:layout_gravity="center_vertical"
                    android:background="@color/dividing_line" />

                <Button
                    android:id="@+id/btn_sure"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@null"
                    android:gravity="center"
                    android:text="确定"
                    android:textColor="#3995fa"
                    android:textSize="@dimen/text_size"
                    android:textStyle="bold" />
            </LinearLayout>
        </LinearLayout>
    </android.support.v7.widget.CardView>
</LinearLayout>      

第二種方式使用DialogFragment實作,考慮到項目中會用到很多dialog,可以将基本的實作稍微提取一下,寫一個基類,如下寫了BaseDialogFragment類,内容如下:

public abstract class BaseDialogFragment extends DialogFragment implements View.OnClickListener{
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //點選外部消失
        getDialog().setCanceledOnTouchOutside(true);
        //點選傳回鍵不消失
        getDialog().setOnKeyListener(new DialogInterface.OnKeyListener() {
            @Override
            public boolean onKey(DialogInterface dialogInterface, int keyCode, KeyEvent keyEvent) {
                if(keyCode == KeyEvent.KEYCODE_BACK){
                    return true;
                }
                return false;
            }
        });
        //将對話框内部的背景設定為透明
        getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

        View rootView = inflater.inflate(getLayout(),container,false);
        findItemView(rootView);
        return rootView;
    }

    public abstract int getLayout() ;

    public abstract void findItemView(View rootView);

    public abstract void onItemClick(View view);
    @Override
    public void onClick(View view) {
       onItemClick(view);
    }
}      

每次顯示dialog時繼承該基類,重寫需要的方法。如下實作的StepLengthFragment,在其中定義了listener,以便實作對話框與調用對話框的activity之間的資料傳遞。

public class StepLengthFragment extends BaseDialogFragment {
    public static final String STEP_LENGTH = "stepLength";
    private StepDataListener listener;

    public interface StepDataListener {
        void setStepData(float stepLen);
    }
    private EditText inputStepLen;
    @Override
    public int getLayout() {
        return R.layout.view_dialog_input;
    }

    public static StepLengthFragment newInstance(float stepLen){
        StepLengthFragment fragment = new StepLengthFragment();
        Bundle bundle = new Bundle();
        bundle.putFloat(STEP_LENGTH,stepLen);
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if(context instanceof StepDataListener){
            listener = (StepDataListener) context;
        }else{
            throw new IllegalArgumentException("activity must implements StepDataListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        listener = null;
    }
    @Override
    public void findItemView(View rootView) {
        TextView msg = (TextView) rootView.findViewById(R.id.tv_msg);
        Button cancel = (Button) rootView.findViewById(R.id.btn_cancle);
        Button sure = (Button) rootView.findViewById(R.id.btn_sure);
        inputStepLen = (EditText) rootView.findViewById(R.id.input);
        msg.setText(R.string.setting_step_length);

        float stepLength = getArguments().getFloat(STEP_LENGTH);
        inputStepLen.setText(String.valueOf(stepLength));

        cancel.setOnClickListener(this);
        sure.setOnClickListener(this);
    }

    @Override
    public void onItemClick(View view) {
        switch (view.getId()) {
            case R.id.btn_cancle:
                getDialog().dismiss();
                break;
            case R.id.btn_sure:
                String val = inputStepLen.getText().toString();
                if(!TextUtils.isEmpty(val) && val.length() > 0){
                    float stepLen = Float.parseFloat(val);
                    //傳回資料給settingactivity
                    listener.setStepData(stepLen);
                } else {
                    Utils.makeToast(getActivity(), getString(R.string.please_input_exact_params));
                }
                getDialog().dismiss();
                break;
            default:
                break;
        }
    }
}      

在調用對話框的activity中實作該接口,以便資料傳遞。 activity中啟動對話框的代碼為:

switch (position) {
    case 0: {
        final float stepLen = setting.getSetpLength();
        holder.desc.setText(String.format(getResources().getString(R.string.stepLen), stepLen));
        convertView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //  stepClick(stepLen);
                StepLengthFragment stepLengthDialog = StepLengthFragment.newInstance(stepLen);
                stepLengthDialog.show(getSupportFragmentManager(), STEP_LENGTH_DIALOG);
            }
        });
    }      

實作該fragment的接口,實作相應的接口

public class SettingActivity extends BaseActivity implements StepLengthFragment.StepDataListener, BodyWeightFragment.WeightDataListener {      
@Override
public void setStepData(float stepLen) {
    Log.e("555", "setStepData: from StepLengthFragment "+stepLen );
    setting.setStepLength(stepLen);
    if (adapter != null) {
        adapter.notifyDataSetChanged();
    }
}      

這種實作dialog的方式不存在第一種手機鍵盤不顯示的問題。