美文网首页Android开发经验谈Android技术知识Android开发
Android 自定义 Style 实现一个简洁、美观、通用 D

Android 自定义 Style 实现一个简洁、美观、通用 D

作者: Android架构师丨小熊 | 来源:发表于2019-07-31 22:05 被阅读0次

    介绍

    今天我们来学习一下如何自定义一个漂亮、美观且通用的对话框。开始前,我们先了解一下对话框(Dialog),它是Android UI交互的一种形式,通常给予用户一个重要事件的通知,让用户来处理这一个事件。它不同于其他几种通知方式,比如Toast、Notification、Snackbar等。这里的不同指的是事件的重要程度,比如我们需要更新软件,那么这时候弹出一个对话框,让用户选择YES/NO;比如更新成功了,我们弹出一个Toast信息“”更新成功了,欢迎使用“”,这样显得更友好。我们应该根据情景更确切的使用哪种交互方式。

    那么,今天我们的主题是一个对话框(Dialog),记得以前刚接触android手机时候,那时的对话框既丑又难看,特别影响整个软件的美观程度,要说以前最好看的还是ios风格。但现在android发展的如此之快,加上google推出的material design风格的各种控件,如果还不够我们还可以自定义定制各种精美样式的控件。现在的android软件UI做的确实挺漂亮的,因为丑的根本没人去用,在这个看脸的时代,软件也是看脸的。

    那么看看我们今天要完成的Dialog长什么样吧,这里我录制了一段动态图,更能体现出效果。

    效果图


    实现步骤

    对话框风格就是这个样子了,我个人感觉还是挺美观的。那么我们来说说它是如何实现的吧。首先,我给它设定了一个风格,也就是对我们对话框一些必要属性的设置,它是一个style资源文件,如下
    
    <style name="MyUsualDialog" parent="android:style/Theme.Dialog">
        <!--背景颜色及和透明程度-->
        <item name="android:windowBackground">@android:color/transparent</item>
        <!--是否去除标题 -->
        <item name="android:windowNoTitle">true</item>
        <!--是否去除边框-->
        <item name="android:windowFrame">@null</item>
        <!--是否浮现在activity之上-->
        <item name="android:windowIsFloating">true</item>
        <!--是否模糊-->
        <item name="android:backgroundDimEnabled">false</item>
    </style>
    

    其次,我们对它的xml布局文件进行绑定,下边是我们布局代码

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        xmlns:tools="http://schemas.android.com/tools"
        android:background="#11ffffff">
     
        <LinearLayout
            android:layout_width="260dp"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:background="@drawable/usual_dialog_shape"
            android:orientation="vertical">
     
            <TextView
                android:id="@+id/tv_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_margin="15dp"
                android:gravity="center"
                tools:text="消息提示"
                android:textColor="#38ADFF"
                android:textSize="16sp" />
     
            <TextView
                android:id="@+id/tv_message"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="20dp"
                android:layout_marginRight="20dp"
                tools:text="提示消息" />
     
            <View
                android:layout_width="match_parent"
                android:layout_height="1px"
                android:layout_marginTop="15dp"
                android:background="#E4E4E4" />
     
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="40dp"
                android:orientation="horizontal">
     
                <Button
                    android:id="@+id/btn_cancel"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_marginLeft="10dp"
                    android:layout_weight="1"
                    android:background="@null"
                    android:gravity="center"
                    android:singleLine="true"
                    tools:text="No"
                    android:textColor="#7D7D7D"
                    android:textSize="16sp"
                    tools:ignore="RtlHardcoded" />
     
                <View
                    android:layout_width="1px"
                    android:layout_height="match_parent"
                    android:background="#E4E4E4" />
     
                <Button
                    android:id="@+id/btn_confirm"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_marginRight="10dp"
                    android:layout_weight="1"
                    android:background="@null"
                    android:gravity="center"
                    android:singleLine="true"
                    tools:text="Yes"
                    android:textColor="#38ADFF"
                    android:textSize="16sp"
                    tools:ignore="RtlHardcoded" />
            </LinearLayout>
        </LinearLayout>
    </RelativeLayout>
    

    最后,我们继承系统的Dialog,进行设置一些必要的style、点击事件等。我们在构造器里传入我们刚刚新建的style主题,这个设置很重要。然后我个人用了建造者模式对Dialog类进行了封装,至于什么是建造者模式,不懂的小伙伴可以看我之前写的一篇关于建造者模式的使用方式:Android设计模式之建造者模式 —— Builder Pattern

    这里贴出整个Dialog类的所有代码,我们命名为UsualDialogger类,就是指通用的对话框。

    /**
     * 通常都会使用的一种交互对话框
     *
     * @Created by Mr.Xu on 2018/4/30.
     */
     
    public class UsualDialogger extends Dialog {
        private final String TITLE;
        private final String MESSAGE;
        private final String CONFIRMTEXT;
        private final String CANCELTEXT;
        private final onConfirmClickListener ONCONFIRMCLICKLISTENER;
        private final onCancelClickListener ONCANCELCLICKLISTENER;
     
        public interface onConfirmClickListener {
            void onClick(View view);
        }
     
        public interface onCancelClickListener {
            void onClick(View view);
        }
     
        private UsualDialogger(@NonNull Context context, String title, String message, String confirmText, String cancelText,
                               onConfirmClickListener onConfirmClickListener, onCancelClickListener onCancelClickListener) {
            super(context, R.style.MyUsualDialog);
            this.TITLE = title;
            this.MESSAGE = message;
            this.CONFIRMTEXT = confirmText;
            this.CANCELTEXT = cancelText;
            this.ONCONFIRMCLICKLISTENER = onConfirmClickListener;
            this.ONCANCELCLICKLISTENER = onCancelClickListener;
        }
     
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.usual_dialog);
            setCanceledOnTouchOutside(false);
            initView();
        }
     
        public static Builder Builder(Context context) {
            return new Builder(context);
        }
     
        private void initView() {
            Button btnConfirm = findViewById(R.id.btn_confirm);
            Button btnCancel = findViewById(R.id.btn_cancel);
            TextView tvTitle = findViewById(R.id.tv_title);
            TextView tvMessage = findViewById(R.id.tv_message);
     
            if (!TextUtils.isEmpty(TITLE)) {
                tvTitle.setText(TITLE);
            }
            if (!TextUtils.isEmpty(MESSAGE)) {
                tvMessage.setText(MESSAGE);
            }
            if (!TextUtils.isEmpty(CONFIRMTEXT)) {
                btnConfirm.setText(CONFIRMTEXT);
            }
            if (!TextUtils.isEmpty(CANCELTEXT)) {
                btnCancel.setText(CANCELTEXT);
            }
     
            btnConfirm.setOnClickListener(view -> {
                if (ONCONFIRMCLICKLISTENER == null) {
                    throw new NullPointerException("clicklistener is not null");
                } else {
                    ONCONFIRMCLICKLISTENER.onClick(view);
                }
            });
            btnCancel.setOnClickListener(view -> {
                if (ONCANCELCLICKLISTENER == null) {
                    throw new NullPointerException("clicklistener is not null");
                } else {
                    ONCANCELCLICKLISTENER.onClick(view);
                }
            });
        }
     
        public UsualDialogger shown() {
            show();
            return this;
        }
     
        public static class Builder {
            private String mTitle;
            private String mMessage;
            private String mConfirmText;
            private String mCancelText;
            private onConfirmClickListener mOnConfirmClickListener;
            private onCancelClickListener mOnCcancelClickListener;
            private Context mContext;
     
            private Builder(Context context) {
                this.mContext = context;
            }
     
            public Builder setTitle(String title) {
                this.mTitle = title;
                return this;
            }
     
            public Builder setMessage(String message) {
                this.mMessage = message;
                return this;
            }
     
            public Builder setOnConfirmClickListener(String confirmText, onConfirmClickListener confirmclickListener) {
                this.mConfirmText = confirmText;
                this.mOnConfirmClickListener = confirmclickListener;
                return this;
            }
     
            public Builder setOnCancelClickListener(String cancelText, onCancelClickListener onCancelclickListener) {
                this.mCancelText = cancelText;
                this.mOnCcancelClickListener = onCancelclickListener;
                return this;
            }
     
            public UsualDialogger build() {
                return new UsualDialogger(mContext, mTitle, mMessage, mConfirmText, mCancelText,
                        mOnConfirmClickListener, mOnCcancelClickListener);
            }
        }
    }
        关键的是我们的MainActivity在使用这种建造者模式调用我们的UsualDialogger确实很舒服,我们的MainActivity代码如下
    
    public class MainActivity extends AppCompatActivity {
     
        @BindView(R.id.btn_Dialog_Usual)
        Button btnDialogUsual;
     
        private UsualDialogger dialog2 = null;
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ButterKnife.bind(this);
        }
     
        /**
         * 通用的确定和取消对话框
         */
        @OnClick(R.id.btn_Dialog_Usual)
        public void showUsualDialog() {
            dialog2 = UsualDialogger.Builder(this)
                    .setTitle("通用对话框")
                    .setMessage("这是一个漂亮的对话框")
                    .setOnConfirmClickListener("确定", view -> {
                        Toast.makeText(MainActivity.this, "确定", Toast.LENGTH_SHORT).show();
                    })
                    .setOnCancelClickListener("取消", view -> {
                        Toast.makeText(MainActivity.this, "取消", Toast.LENGTH_SHORT).show();
                        if (dialog2 != null) {
                            dialog2.dismiss();
                        }
                    })
                    .build()
                    .shown();
        }
    }
    

    可以看到在确定、取消事件中,我们只打了一个Toast来简单的测试,在这里可以处理点击事件。那么这就是我们实现的所有代码,完成了我们的一个简单的自定义对话框。

    最后

    最后我准备了一些面试的知识汇总,数据结构,计算机网络等等都有。自己整理和分类的,还请尊重知识产出。
    分享给大家的资料包括高级架构技术进阶脑图、Android开发面试专题资料,还有高级进阶架构资料包括但不限于【高级UI、性能优化、移动架构师、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术】希望能帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也是可以分享给身边好友一起学习的!

    资料免费领取方式:加群797404811

    相关文章

      网友评论

        本文标题:Android 自定义 Style 实现一个简洁、美观、通用 D

        本文链接:https://www.haomeiwen.com/subject/blvxdctx.html