安全卫士第三课 设置中心界面——自定义View学习

来源:互联网 发布:精通android网络开发 编辑:程序博客网 时间:2024/06/04 23:06
 
点击进入自然不必说很容易 

这里主要是实现了一个自定义View  以及标题栏使用了style

1 标题栏的style

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

<!--    <TextView
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:textSize="30dp"
        android:gravity="center"
        android:textColor="@color/black"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="功能列表"
        android:background="@color/lightsteelblue"
        android:id="@+id/textView" />-->

    <style name="TitleStyle" >
        <!-- Customize your theme here. -->
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">60dp</item>
        <item name="android:textSize">30dp</item>
        <item name="android:gravity">center</item>
        <item name="android:textColor">@color/black</item>
        <item name="android:background">@color/lightsteelblue</item>
    </style>
</resources>
这里贴上style.xml所有的代码  是因为当你不知道如何去设置style的时候就可以参照已经存在的style
来设置
然后在布局文件中引用就可以了

<TextView
    style="@style/TitleStyle"
    android:text="@string/settingTitle"/>

2 自定义SettingItemView 
这里我们需要多个红色方框中的样式 两个textview 一个checkbox 所以使用自定义view是最方便的

自定义组件

第一步 自定义一个view ,继承ViewGroup 这里是继承了RelativeLayout

public class SettingItemView extends RelativeLayout {

第二步 填入方法 ,并为自定义组合控件 填入编写好的布局文件,在自定义的view中加载


<?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="75dp"
        android:padding="8dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:id="@+id/tv_title"
            android:textSize="20sp"
            android:layout_alignParentTop="true"
            android:layout_alignParentStart="true" />

        <!--透明度第四位从0到f-->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:id="@+id/tv_desc"
            android:textSize="15sp"
            android:layout_marginTop="3dp"
            android:textColor="#a000"
            android:layout_below="@+id/tv_title"
            android:layout_alignParentStart="true" />

        <CheckBox
            android:clickable="false"
            android:focusable="false"
            android:focusableInTouchMode="true"
            android:id="@+id/cb_status"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"/>
        <View
            android:layout_width="match_parent"
            android:layout_height="0.2dp"
            android:background="#a000"
            android:layout_alignParentBottom="true"
            />
    </RelativeLayout>


这里因为并没有为两个textview填写text所以显示为没有内容

注意 代码中的高亮区域其实就是画出了这么一条横线

然后在自定义控件代码中这样去加载

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(){
    //将定义好的布局文件设置给当前的SettingItemView
    View.inflate(getContext(),R.layout.view_setting_item,this);
    tvTitle= (TextView) findViewById(R.id.tv_title);
    tvDesc= (TextView) findViewById(R.id.tv_desc);
    cbStatus= (CheckBox) findViewById(R.id.cb_status);
}
高亮区域的最后一个参数 是指 将布局文件中的组合控件填写在 this 这个RelativeLayout中
也正是因为布局文件就在viewgroup中所以初始化控件的时候可以直接findviewbyid()
我们可以为控件设置方法为其填入相应的数据

public void setTitle(String title){
    tvTitle.setText(title);
}
 public void setDesc(String desc){
     tvDesc.setText(desc);
 }
/*
*返回勾选状态
* */
public boolean isChecked(){
    return cbStatus.isChecked();
}

public void setChecked(boolean checked){
    cbStatus.setChecked(checked);
}
自定义控件完成之后 可以在布局文件中加载


<skkk.admin.com.newgoal.view.SettingItemView
    android:id="@+id/siv_update"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    >

然后在activity中进行控制

/**
* Created by admin on 2016/5/12.
*/
public class SettingActivity extends AppCompatActivity {
    private SettingItemView sivUpdate;
    private SharedPreferences mPref;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.setting_layout);
        sivUpdate= (SettingItemView) findViewById(R.id.siv_update);//初始化自定义View

/*
对自定义View进行事件监听
*/
        sivUpdate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //判断当前勾选状态
                if(sivUpdate.isChecked()){
                    //设置不勾选
                    sivUpdate.setChecked(false);
                    sivUpdate.setDesc("关闭")
                }else{
                    sivUpdate.setChecked(true);
                    sivUpdate.setDesc("开启")
                }
            }
        });
    }
}

这样基本完成了点击自定义view checkbox会跟着变化
这里有一个细节 当我们点击view的时候监听事件被触发 tv_desc 内容发生变化
但是当我们点击checkbox的时候 并不能触发事件 
所以我们可以选择让checkbox无法获取焦点 点击哪里都是点击view

在自定义控件的布局文件中 三个false搞定
<CheckBox
    android:clickable="false"
    android:focusable="false"
    android:focusableInTouchMode="true"
    android:id="@+id/cb_status"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:layout_centerVertical="true"/>

当然这里有个问题 我们需求的是设置是否自动更新 对于用户选择的结果我们要记录下来
所以使用 SharedPreferences

public class SettingActivity extends AppCompatActivity {
    private SettingItemView sivUpdate;
    private SharedPreferences mPref;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.setting_layout);
        mPref=getSharedPreferences("config",MODE_PRIVATE);
        sivUpdate= (SettingItemView) findViewById(R.id.siv_update);
        boolean autoUpdate=mPref.getBoolean("auto_update",true);

        if(autoUpdate){
            sivUpdate.setChecked(true);
        }else{
            sivUpdate.setChecked(false);
        }

        sivUpdate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //判断当前勾选状态
                if(sivUpdate.isChecked()){
                    //设置不勾选
                    sivUpdate.setChecked(false);
                    //更新SP
                    mPref.edit().putBoolean("auto_update",false).commit();
                }else{
                    sivUpdate.setChecked(true);
                    //更新SP
                    mPref.edit().putBoolean("auto_update",true).commit();
                }
            }
        });
    }
}
当checkbox勾选的时候更新SP为true 反之就是false
然后在每次activity onCreate的时候调取key:auto_update 根据获取到的boolean来判断是否更新
在闪屏页Activity中

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.splash_layout);
//        初始化控件
        tvVersion= (TextView) findViewById(R.id.splash_version);
        tvVersion.setText("版本号: "+getVersionName());
//        方法:检查版本
        mPref=getSharedPreferences("config",MODE_PRIVATE);
        boolean autoUpdate=mPref.getBoolean("auto_update",true);
        if(autoUpdate){
            checkVerson();
        }else {
            mHandler.sendEmptyMessageDelayed(CODE_ENTER_HOME,2000);
            //延时两秒后发送消息
        }
    }
如果获取的boolean为true就检查更新 否则延迟两秒发送进入主界面消息

当然设置页面也有对应的给checkbox勾选

mPref=getSharedPreferences("config",MODE_PRIVATE);
sivUpdate= (SettingItemView) findViewById(R.id.siv_update);
boolean autoUpdate=mPref.getBoolean("auto_update",true);

if(autoUpdate){
    sivUpdate.setChecked(true);
}else{
    sivUpdate.setChecked(false);
}
这里可以发现 在SettingActivity中并没有使用自定义控件中的setDesc()与setTitle()方法来给自定义控件的textview进行赋值
这里就隐身到了一个重要的技巧,即:

3 自定义控件的自定义属性

第一步 自定义属性
在value中新建一个attrs.xml文件

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="SettingItemView">
        <attr name="titleText" format="string"/>
        <attr name="desc_on" format="string"/>
        <attr name="desc_off" format="string"/>
    </declare-styleable>
</resources>
这里将自定义属性的name 设置为SettingItemView 即自定义View的名字然后对应的自定义一些属性
如 自定义 titleText 内容为String/desc_on内容为String/desc_off内容为String
然后我们到引用自定义view的布局(设置中心布局文件)中去申明

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:itheima="http://schemas.android.com/apk/res-auto" //前缀标记:。。。。。包名(androidstudio中默认为res-auto)
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        style="@style/TitleStyle"
        android:text="@string/settingTitle"/>

    <skkk.admin.com.newgoal.view.SettingItemView
        android:id="@+id/siv_update"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        itheima:titleText="自动更新设置" 
        itheima:desc_on="自动更新设置已开启"   
        itheima:desc_off="自动更新设置已关闭"
        >
    </skkk.admin.com.newgoal.view.SettingItemView>
    <!--skkk.admin.com.newgoal-->
</LinearLayout>
这样就给我们自定义的三个属性添加到了自定义View中

然后在自定义view中我们对属性进行获取

public SettingItemView(Context context, AttributeSet attrs) {
    super(context, attrs);
    //根据属性名称获取属性的值
    mTitle=attrs.getAttributeValue(NAMESPACE,"titleText");
    mDescOn=attrs.getAttributeValue(NAMESPACE,"desc_on");
    mDescOff=attrs.getAttributeValue(NAMESPACE,"desc_off");
    initView();

}
这个方法是当view使用属性的时候调用 我们分别获取到我们自定义的三个属性内容

然后在初始化布局方法 initView()中给tv_title添加内容

private void initView(){
    //将定义好的布局文件设置给当前的SettingItemView
    View.inflate(getContext(),R.layout.view_setting_item,this);
    tvTitle= (TextView) findViewById(R.id.tv_title);
    tvDesc= (TextView) findViewById(R.id.tv_desc);
    cbStatus= (CheckBox) findViewById(R.id.cb_status);
    setTitle(mTitle);//设置标题
}
接着当我们修改checkbox的勾选状态时自动修改tv_desc的内容

public void setChecked(boolean checked){
    cbStatus.setChecked(checked);
    //根据选择的状态更新文本描述
    if(checked){
        setDesc(mDescOn);
    }else{
        setDesc(mDescOff);
    }
}

这样就完成了在view内部自动匹配对应的描述 
简直不要太炫酷~~~~

最后自定义View的代码如下:

package skkk.admin.com.newgoal.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.CheckBox;
import android.widget.RelativeLayout;
import android.widget.TextView;

import skkk.admin.com.newgoal.R;

/**
* Created by admin on 2016/5/12.
* 设置中心的自定义View
* 自定义组合控件
*/
public class SettingItemView extends RelativeLayout {

    private final String NAMESPACE="http://schemas.android.com/apk/res-auto";
    private TextView tvTitle,tvDesc;
    private CheckBox cbStatus;
    private String mTitle,mDescOn,mDescOff;

    public SettingItemView(Context context) {
        super(context);
        initView();
    }

    public SettingItemView(Context context, AttributeSet attrs) {
        super(context, attrs);
        //根据属性名称获取属性的值
        mTitle=attrs.getAttributeValue(NAMESPACE,"titleText");
        mDescOn=attrs.getAttributeValue(NAMESPACE,"desc_on");
        mDescOff=attrs.getAttributeValue(NAMESPACE,"desc_off");
        initView();

    }

    public SettingItemView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

    /*
    初始化布局
    */
    private void initView(){
        //将定义好的布局文件设置给当前的SettingItemView
        View.inflate(getContext(),R.layout.view_setting_item,this);
        tvTitle= (TextView) findViewById(R.id.tv_title);
        tvDesc= (TextView) findViewById(R.id.tv_desc);
        cbStatus= (CheckBox) findViewById(R.id.cb_status);
        setTitle(mTitle);//设置标题
    }

    public void setTitle(String title){
        tvTitle.setText(title);
    }
    public void setDesc(String desc){
        tvDesc.setText(desc);
    }
    /*
    *返回勾选状态
    * */
    public boolean isChecked(){
        return cbStatus.isChecked();
    }

    public void setChecked(boolean checked){
        cbStatus.setChecked(checked);
        //根据选择的状态更新文本描述
        if(checked){
            setDesc(mDescOn);
        }else{
            setDesc(mDescOff);
        }
    }
}

而设置中心activity中代码就可以不用手动修改自定义view中的text
而只需要修改check的状态就可以了
代码如下

package skkk.admin.com.newgoal.activity;

import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

import skkk.admin.com.newgoal.R;
import skkk.admin.com.newgoal.view.SettingItemView;

/**
* Created by admin on 2016/5/12.
*/
public class SettingActivity extends AppCompatActivity {
    private SettingItemView sivUpdate;
    private SharedPreferences mPref;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.setting_layout);
        mPref=getSharedPreferences("config",MODE_PRIVATE);
        sivUpdate= (SettingItemView) findViewById(R.id.siv_update);
        boolean autoUpdate=mPref.getBoolean("auto_update",true);

        if(autoUpdate){
            sivUpdate.setChecked(true);
        }else{
            sivUpdate.setChecked(false);
        }

        sivUpdate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //判断当前勾选状态
                if(sivUpdate.isChecked()){
                    //设置不勾选
                    sivUpdate.setChecked(false);
                    //更新SP
                    mPref.edit().putBoolean("auto_update",false).commit();
                }else{
                    sivUpdate.setChecked(true);
                    //更新SP
                    mPref.edit().putBoolean("auto_update",true).commit();
                }
            }
        });
    }
}
ok最后的效果就出来了

  
0 0
原创粉丝点击