Android项目:手机安全卫士(4)—— 自定义(组合)控件、属性

来源:互联网 发布:电梯安全员考试软件 编辑:程序博客网 时间:2024/06/03 19:06

Android项目:手机安全卫士(4)—— 自定义(组合)控件、属性

1 总纲

手机安全卫士共有 9 个功能,我们先来看看设置界面长什么样:

设置界面

大家已经发现了,第一反应就是用 ListView 实现,但是,我们仔细一看,每一个 Item 并不完全一样,况且 Item 数量也不多,所以,我们可以用自定义(组合)控件来实现,把每一个 Item 抽象出来,做成控件,之所以叫组合控件,因为这个控件中用到了很多系统控件,我们只是修改了它们的布局而已。

关于项目相关文章,请访问:

  • Android 项目:手机安全卫士(1)—— 闪屏界面
  • Android 项目:手机安全卫士(2)—— 版本升级
  • Android 项目:手机安全卫士(3)—— 主界面布局

项目源码地址(实时更新):https://github.com/xwdoor/MobileSafe

2 自定义组合控件

先按照上图中的自动更新设置为模板进行实现,包括四个控件:两个 TextView,一个 CheckBox,一条横线。其中横线的实现思路很有意思,它也是一个 TextView,只是设置了它的高度为 1 个像素,然后这是背景为黑色即可。好了,废话不多说,开始写代码,首先创建布局文件:item_setting.xml,内容如下:

    <?xml version="1.0" encoding="utf-8"?>    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"        android:orientation="vertical" android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:padding="5dp">        <TextView            android:id="@+id/tv_title"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:textSize="20sp"            android:text="自动更新设置"            android:textColor="@android:color/black"/>        <TextView            android:id="@+id/tv_desc"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginTop="5dp"            android:text="自动更新已开启"            android:layout_below="@id/tv_title"            android:textColor="#b000"/>        <CheckBox            android:id="@+id/cb_check"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:clickable="false"            android:focusableInTouchMode="false"            android:focusable="false"            android:layout_alignParentRight="true"            android:layout_centerVertical="true"/>        <TextView            android:layout_width="match_parent"            android:layout_height="1px"            android:background="@android:color/black"            android:layout_marginTop="5dp"            android:layout_below="@id/tv_desc"/>    </RelativeLayout>

这就是自动更新设置的 UI 实现了,注意,该布局中屏蔽了 CheckBox 的点击事件,并且不让它获取焦点。接下来就是创建自定义组件,且使用该 UI 作为界面。创建类:SettingItemView,继承自 RelativeLayout,代码如下:

    /**     * Created by XWdoor on 2016/3/1 001 16:19.     * 博客:http://blog.csdn.net/xwdoor     */    public class SettingItemView extends RelativeLayout {        private TextView tvTitle;        private TextView tvDesc;        private CheckBox cbCheck;        public SettingItemView(Context context) {            super(context);            initView();        }        public SettingItemView(Context context, AttributeSet attrs) {            super(context, attrs);            initView();        }        public SettingItemView(Context context, AttributeSet attrs, int defStyleAttr) {            super(context, attrs, defStyleAttr);            initView();        }        private void initView(){            View view = View.inflate(getContext(), R.layout.item_setting,null);            tvTitle = (TextView) view.findViewById(R.id.tv_title);            tvDesc = (TextView) view.findViewById(R.id.tv_desc);            cbCheck = (CheckBox) view.findViewById(R.id.cb_check);            addView(view);        }        /** 设置标题 */        public void setTitle(String title){            tvTitle.setText(title);        }        /** 设置描述 */        public void setDesc(String desc){            tvDesc.setText(desc);        }        /** 是否开启 */        public boolean isChecked(){            return cbCheck.isChecked();        }        /** 设置开启状态 */        public void setChecked(boolean checked){            cbCheck.setChecked(checked);        }    }

SettingItemView 使用了先前定义的布局,并对外公开 4 个接口,分别是:设置标题、设置描述、获取开启状态、设置开启状态。接下来就是使用它了,先是创建 SettingActivity,及其布局文件:activity_setting.xml,在布局文件中,使用刚才自定义的控件,代码如下:

    <?xml version="1.0" encoding="utf-8"?>    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="vertical">        <TextView            android:id="@+id/tv_title"            style="@style/TitleBar"            android:text="设置"/>        <!-- 自定义控件 -->        <net.xwdoor.mobilesafe.view.SettingItemView            android:id="@+id/siv_update"            android:layout_width="match_parent"            android:layout_height="wrap_content"/>    </LinearLayout>

至此,自定义控件就弄好了,然后我们就可以像其他普通控件一样使用它了,以下是 SettingActivity 中的代码:

    @Override    protected void initViews(Bundle savedInstanceState) {        setContentView(R.layout.activity_setting);        final SettingItemView sivUpdate = (SettingItemView) findViewById(R.id.siv_update);        sivUpdate.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                sivUpdate.setChecked(!sivUpdate.isChecked());                if(sivUpdate.isChecked()){                    //若选中,开启自动更新设置                    sivUpdate.setDesc("自动更新已开启");                }else {                    //关闭自动更新                    sivUpdate.setDesc("自动更新已关闭");                }            }        });    }

运行结果如图:

自动更新设置

3 自定义属性

聪明的你已经发现了,每次点击时,我们都要设置它的描述,sivUpdate.setDesc("自动更新已开启"); 是已开启,sivUpdate.setDesc("自动更新已关闭"); 是已关闭,一个 Item 还好,但是如果有很多个的话,管理起来就比较麻烦了,而且文字常量显示什么的属于 UI 的数据,应该在设计 UI 的时候就设置好的,所以,我们最好将这几个状态,以及标题,设置为 SettingItemView 的属性,也就是我们的自定义属性。

res->values 文件夹中创建资源文件:attr.xml,因为我使用的是 Android Studio,不存在该文件,所以手动创建,然后写自定义属性,代码如下:

    <?xml version="1.0" encoding="utf-8"?>    <resources>        <declare-styleable name="SettingItemView">            <attr name="stitle" format="string" />            <attr name="desc_on" format="string" />            <attr name="desc_off" format="string" />        </declare-styleable>    </resources>

其中 name 是自定义的,format 是该属性的值类型。好了,很简单吧,接下来使用它了,首先在布局文件的根节点中,为自定义属性声明一个命名空间:xmlns:xwdoor="http://schemas.android.com/apk/res-auto", 其中,xwdoor 是自定义部分,这样,系统就可以找到我们的自定义属性文件的位置,然后就可以直接用了,代码如下:

    <!-- 自定义控件 -->    <net.xwdoor.mobilesafe.view.SettingItemView        android:id="@+id/siv_update"        android:layout_width="match_parent"        android:layout_height="wrap_content"        xwdoor:stitle="自动更新设置"        xwdoor:desc_on="自动更新已开启"        xwdoor:desc_off="自动更新已关闭"/>

当然,仅仅是这样,我们是看不到效果的,我们还需要在自定义控件 SettingItemView 中做一些修改才行,代码如下:

/** * Created by XWdoor on 2016/3/1 001 16:19. * 博客:http://blog.csdn.net/xwdoor */public class SettingItemView extends RelativeLayout {    public static final String NAMESPACE_XWDOOR = "http://schemas.android.com/apk/res-auto";    private String mDescOff;    private String mDescOn;    private TextView tvTitle;    private TextView tvDesc;    private CheckBox cbCheck;    public SettingItemView(Context context) {        super(context);        initView();    }    public SettingItemView(Context context, AttributeSet attrs) {        super(context, attrs);        int attrCount = attrs.getAttributeCount();        //获取stitle属性的值        String title = attrs.getAttributeValue(NAMESPACE_XWDOOR, "stitle");        //获取关闭设置时的描述        mDescOn = attrs.getAttributeValue(NAMESPACE_XWDOOR, "desc_on");        //获取开启设置时的描述        mDescOff = attrs.getAttributeValue(NAMESPACE_XWDOOR, "desc_off");        initView();        setTitle(title);        setDesc(mDescOff);    }    public SettingItemView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        initView();    }    /** 设置开启状态 */    public void setChecked(boolean checked){        cbCheck.setChecked(checked);        if(checked){            setDesc(mDescOn);        }else {            setDesc(mDescOff);        }    }}

4 总结

好了,到此,我们的自定义组合控件、自定义属性就完成了,本文主要是关于 UI 设计与实现,没有多大难度,主要是知识点的整合与熟悉,且整个项目基本如此,都是熟悉 Android 开发的特性、熟悉代码风格、掌握知识点。

关于项目相关文章,请访问:

  • Android 项目:手机安全卫士(1)—— 闪屏界面
  • Android 项目:手机安全卫士(2)—— 版本升级
  • Android 项目:手机安全卫士(3)—— 主界面布局

项目源码地址(实时更新):https://github.com/xwdoor/MobileSafe

0 0