DataBinding的使用——换肤方案的实现

来源:互联网 发布:冷核聚变知乎 编辑:程序博客网 时间:2024/05/17 06:08

在学习了DataBinding框架后,就想着这个方案在一些场景下的运用,于是根据这个框架的特性,写出了一个换肤的方案,先看效果图:

DataBinding换肤

在看下面的实现之前,希望你对DataBinding框架有基本的认识。如果你不够了解,可以参考我之前的一片文章Android 官方框架DataBinding学习笔记,或者参考官方文档。

这个换肤的方案支持字体大小、颜色,背景色以及图片的切换,所以先创建实体类:

public class StyleBean extends BaseObservable{    /**     * 字体大小的级别 0-5     */    @Bindable    private int textSizeLivel;    /**     * 主题风格 白天或者黑夜     */    @Bindable    private boolean isNight;    public int getTextSizeLivel()    {        return textSizeLivel;    }    public void setTextSizeLivel(int textSizeLivel)    {        this.textSizeLivel = textSizeLivel;        notifyPropertyChanged(BR.textSizeLivel);    }    public boolean isNight()    {        return isNight;    }    public void setNight(boolean night)    {        isNight = night;        notifyPropertyChanged(BR._all);    }    public StyleBean(int textSizeLivel, boolean isNight)    {        this.textSizeLivel = textSizeLivel;        this.isNight = isNight;    }}

继承BaseObservable类是为了之后修改属性能自动更新UI
然后准备好字体大小以及颜色值的xml文件:

<?xml version="1.0" encoding="utf-8"?><resources>    <dimen name="size_level_0">10sp</dimen>    <dimen name="size_level_1">12sp</dimen>    <dimen name="size_level_2">14sp</dimen>    <dimen name="size_level_3">16sp</dimen>    <dimen name="size_level_4">18sp</dimen>    <dimen name="size_level_5">20sp</dimen>    <color name="textColorNight">#222222</color>    <color name="textColorDay">#aaaaaa</color>    <color name="backgroundNight">#999999</color>    <color name="backgroundDay">#eeeeee</color></resources>

直接在实体类里面去初始化这些资源:

    public StyleBean(int textSizeLivel, boolean isNight)    {        ···        initResource();    }    private void initResource()    {        dimens = new float[6];        Resources resources = BaseApplication.getContext().getResources();        dimens[0] = resources.getDimension(R.dimen.size_level_0);        dimens[1] = resources.getDimension(R.dimen.size_level_1);        dimens[2] = resources.getDimension(R.dimen.size_level_2);        dimens[3] = resources.getDimension(R.dimen.size_level_3);        dimens[4] = resources.getDimension(R.dimen.size_level_4);        dimens[5] = resources.getDimension(R.dimen.size_level_5);        mColorDay = resources.getColor(R.color.textColorDay);        mColorNight = resources.getColor(R.color.textColorNight);        mBackgroundDay = resources.getColor(R.color.backgroundDay);        mBackgroundNight = resources.getColor(R.color.backgroundNight);    }

然后添加自定义setter方法:

    @BindingAdapter("android:textSize")    public static void setTextSize(TextView textView, int level)    {        textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, StyleBean.dimens[level]);    }    @BindingAdapter("android:textColor")    public static void setTextColor(TextView textView, boolean isNight)    {        textView.setTextColor(isNight ? StyleBean.mColorNight : StyleBean.mColorDay);    }    @BindingAdapter("android:background")    public static void setBackground(View view, boolean isNight)    {        view.setBackgroundColor(isNight ? mBackgroundNight : mBackgroundDay);    }

这样,当我们在控件的属性使用表达式设置值,切表达式返回类型兼容我们的方法时,就会调用我们的方法。

然后就可以在layout文件里面书写代码了:

<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android"        xmlns:app="http://schemas.android.com/apk/res-auto"        xmlns:tools="http://schemas.android.com/tools">    <data>        <import type="com.example.xujiafeng.skinpeeler.StyleBean"/>        <variable            name="style"            type="StyleBean"/>    </data>    <RelativeLayout        android:background="@{style.night}"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="vertical"        android:padding="20dp"        tools:context="com.example.xujiafeng.skinpeeler.activity.MainActivity">        <LinearLayout            android:id="@+id/layout1"            android:layout_width="wrap_content"            android:layout_height="wrap_content">            <TextView                android:id="@+id/text"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:text="待设置的字体"                android:textColor="@{style.night}"                android:textSize="@{style.textSizeLivel}"/>        </LinearLayout>        <ImageView            android:id="@+id/image"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_below="@+id/layout"            android:layout_marginTop="10dp"            android:src="@{style.night ? @drawable/icon_vip_check:@drawable/icon_vip_uncheck}"/>        <Button            android:id="@+id/button_text_size"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentBottom="true"            android:text="设置字体大小"/>        <Button            android:id="@+id/button_day"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentBottom="true"            android:layout_alignParentRight="true"            android:text="风格"/>    </RelativeLayout></layout>

由于我是把自定义setter写在StyleBean里面,所以必须要导入这个类。

为了实现App风格的一致,所以将StyleBean的实现类放在Application里面,并添加设置风格的方法:

public class BaseApplication extends Application{    @Override    public void onCreate()    {        super.onCreate();        sContext = this;        style = new StyleBean(2, false);    }    private static StyleBean style;    public static StyleBean getStyle()    {        return style;    }    public static Context sContext;    public static Context getContext()    {        return sContext;    }    public static void setTextSize(int level)    {        style.setTextSizeLivel(level);    }    public static void setNight(boolean isNight)    {        style.setNight(isNight);    }    public static int getTextSize()    {        return style.getTextSizeLivel();    }    public static boolean getNight()    {        return style.isNight();    }}

然后在Activity里面设置风格的时候,使用Application里面的全局style,完整的代码如下:

public class MainActivity extends AppCompatActivity{    private ActivityMainBinding mBinding;    @Override    protected void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);        mBinding.setStyle(BaseApplication.getStyle());    }}

添加修改style的方法在StyleBean中,供按钮去添加事件:

public class StyleBean extends BaseObservable{    public void changeTextSize(View view)    {        final String[] items = {"0", "1", "2", "3", "4", "5"};        new AlertDialog.Builder(view.getContext()).setItems(items, new DialogInterface.OnClickListener()        {            @Override            public void onClick(DialogInterface dialogInterface, int i)            {                BaseApplication.setTextSize(Integer.valueOf(items[i]));            }        }).create().show();    }    public void changeNight(View view)    {        final String[] items = {"夜间", "白天"};        new AlertDialog.Builder(view.getContext()).setItems(items, new DialogInterface.OnClickListener()        {            @Override            public void onClick(DialogInterface dialogInterface, int i)            {                BaseApplication.setNight(i == 0);            }        }).create().show();    }}
        <Button            android:id="@+id/button_text_size"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentBottom="true"            android:onClick="@{(view)->style.changeTextSize(view)}"            android:text="设置字体大小"/>        <Button            android:id="@+id/button_day"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentBottom="true"            android:layout_alignParentRight="true"            android:onClick="@{(view)->style.changeNight(view)}"            android:text="风格"/>

这样点击按钮就能够弹窗选择字体大小或者白天黑夜了。

项目的GitHub地址

原创粉丝点击