美文网首页android系统控件安卓实用知识Android学习知识
Android 深入(二)- 利用ToolBar实现动态主题

Android 深入(二)- 利用ToolBar实现动态主题

作者: JeenWang | 来源:发表于2017-02-27 17:34 被阅读1862次

    利用ToolBar实现主题切换原理:切换主题时,将颜色值存储到Preference中,同时更新主题样式。再次打开App读取Preference对应的颜色值,设置主题样式即可。

    • 主要使用方法如下:
      1)设置ToolBar的背景颜色:toolbar.setBackgroundColor()。
      2)设置窗体状态栏透明:getWindow().setStatusBarColor()。
      3)设置窗体导航栏底色:getWindow().setNavigationBarColor();

    首先看一下效果图:

    converted_file_44df3f12.gif
    1. 创建一个Activity ,设置主题为"@style/Theme.AppCompat.Light.NoActionBar"。
    <activity android:name=".MainActivity"
                android:theme="@style/Theme.AppCompat.Light.NoActionBar">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
    
    2. 在style.xml中自定义主题样式。
    <resources xmlns:tools="http://schemas.android.com/tools">
    
        <!-- Base application theme. -->
        <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
            <!-- Customize your theme here. -->
            <item name="colorPrimary">@color/accent_amber</item>
            <item name="colorPrimaryDark">@color/accent_amber</item>
            <item name="colorAccent">@color/accent_amber</item>
        </style>
    
        <style name="MyToolbar" parent="Widget.AppCompat.Toolbar">
            <item name="android:layout_width">match_parent</item>
            <item name="android:layout_height">wrap_content</item>
            <item name="android:elevation" tools:ignore="NewApi">5dp</item>
            <item name="theme">@style/MyToolbarTheme</item>
    
        </style>
    
        <style name="MyToolbarTheme" parent="ThemeOverlay.AppCompat.ActionBar">
            <item name="android:textColorPrimary">#FFF</item>
            <item name="colorControlNormal">#FFF</item>
            <item name="colorControlHighlight">#FFF</item>
        </style>
    </resources>
    
    
    3. 自定义toolbar.xml,使用自定义的主题MyToolBar。
    <?xml version="1.0" encoding="utf-8"?>
    <android.support.v7.widget.Toolbar
        xmlns:android="http://schemas.android.com/apk/res/android"
        style="@style/MyToolbar"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        />
    
    4. 在Activity布局中使用toolbar.xml。
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <include
            android:id="@+id/toolbar"
            layout="@layout/toolbar" />
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!" />
    </LinearLayout>
    
    
    5. 设置主题基础ThemeActivity,负责设置更改主题。
    package cn.studyou.themedeep.base;
    
    import android.annotation.TargetApi;
    import android.app.ActivityManager;
    import android.content.Context;
    import android.graphics.drawable.BitmapDrawable;
    import android.graphics.drawable.Drawable;
    import android.os.Build;
    import android.os.Bundle;
    import android.support.v4.content.ContextCompat;
    import android.support.v7.app.AppCompatActivity;
    import android.support.v7.widget.SwitchCompat;
    import android.widget.ArrayAdapter;
    import android.widget.EditText;
    import android.widget.RadioButton;
    import android.widget.ScrollView;
    import android.widget.SeekBar;
    
    import com.mikepenz.iconics.IconicsDrawable;
    import com.mikepenz.iconics.context.IconicsContextWrapper;
    import com.mikepenz.iconics.typeface.IIcon;
    
    import java.util.ArrayList;
    
    import cn.studyou.themedeep.R;
    import cn.studyou.themedeep.utils.ColorPaletteUtils;
    import cn.studyou.themedeep.utils.PreferenceUtils;
    import cn.studyou.themedeep.utils.ThemeUtils;
    
    /**
     * 基本功能:主题
     * 创建:王杰
     * 创建时间:2017/2/27
     * 邮箱:w489657152@gmail.com
     */
    
    public class ThemeActivity extends AppCompatActivity {
        private ThemeUtils themeUtils;
        private PreferenceUtils SP;
        private boolean coloredNavBar;
        private boolean obscuredStatusBar;
        private boolean applyThemeImgAct;
    
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            SP = PreferenceUtils.getInstance(getApplicationContext());
            themeUtils = new ThemeUtils(getApplicationContext());
        }
    
        @Override
        public void onResume() {
            super.onResume();
            updateTheme();
        }
    
        public void updateTheme() {
            themeUtils.updateTheme();
            coloredNavBar = SP.getBoolean(getString(R.string.preference_colored_nav_bar), false);
            obscuredStatusBar = SP.getBoolean(getString(R.string.preference_translucent_status_bar), true);
            applyThemeImgAct = SP.getBoolean(getString(R.string.preference_apply_theme_pager), true);
        }
    
        @Override
        protected void attachBaseContext(Context newBase) {
            // NOTE: icons stuff
            super.attachBaseContext(IconicsContextWrapper.wrap(newBase));
        }
    
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        public void setNavBarColor() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                if (isNavigationBarColored()) getWindow().setNavigationBarColor(getPrimaryColor());
                else
                    getWindow().setNavigationBarColor(ContextCompat.getColor(getApplicationContext(), R.color.md_black_1000));
            }
        }
    
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        protected void setStatusBarColor() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                if (isTranslucentStatusBar())
                    getWindow().setStatusBarColor(ColorPaletteUtils.getObscuredColor(getPrimaryColor()));
                else
                    getWindow().setStatusBarColor(getPrimaryColor());
            }
        }
    
        protected void setScrollViewColor(ScrollView scr) {
            themeUtils.setScrollViewColor(scr);
        }
    
        public void setCursorDrawableColor(EditText editText, int color) {
            // TODO: 02/08/16 remove this
            ThemeUtils.setCursorDrawableColor(editText, color);
        }
    
    
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        public void setRecentApp(String text) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                BitmapDrawable drawable = ((BitmapDrawable) getDrawable(R.mipmap.ic_launcher));
                setTaskDescription(new ActivityManager.TaskDescription(text, drawable.getBitmap(), getPrimaryColor()));
            }
        }
    
    
        public boolean isNavigationBarColored() {
            return coloredNavBar;
        }
    
        public boolean isTranslucentStatusBar() {
            return obscuredStatusBar;
        }
    
        protected boolean isApplyThemeOnImgAct() {
            return applyThemeImgAct;
        }
    
        protected boolean isTransparencyZero() {
            return 255 - SP.getInt(getString(R.string.preference_transparency), 0) == 255;
        }
    
        public int getTransparency() {
            return 255 - SP.getInt(getString(R.string.preference_transparency), 0);
        }
    
        public void setBaseTheme(int baseTheme, boolean permanent) {
            themeUtils.setBaseTheme(baseTheme, permanent);
        }
    
        public void themeSeekBar(SeekBar bar) {
            themeUtils.themeSeekBar(bar);
        }
    
        public int getPrimaryColor() {
            return themeUtils.getPrimaryColor();
        }
    
        public int getAccentColor() {
            return themeUtils.getAccentColor();
        }
    
        public int getBaseTheme() {
            return themeUtils.getBaseTheme();
        }
    
        protected int getBackgroundColor() {
            return themeUtils.getBackgroundColor();
        }
    
        protected Drawable getPlaceHolder() {
            return themeUtils.getPlaceHolder();
        }
    
        protected int getInvertedBackgroundColor() {
            return themeUtils.getInvertedBackgroundColor();
        }
    
        public int getTextColor() {
            return themeUtils.getTextColor();
        }
    
        public int getSubTextColor() {
            return themeUtils.getSubTextColor();
        }
    
        public int getCardBackgroundColor() {
            return themeUtils.getCardBackgroundColor();
        }
    
        public int getIconColor() {
            return themeUtils.getIconColor();
        }
    
        protected int getDrawerBackground() {
            return themeUtils.getDrawerBackground();
        }
    
        public int getDialogStyle() {
            return themeUtils.getDialogStyle();
        }
    
        protected int getPopupToolbarStyle() {
            return themeUtils.getPopupToolbarStyle();
        }
    
        protected ArrayAdapter<String> getSpinnerAdapter(ArrayList<String> items) {
            return themeUtils.getSpinnerAdapter(items);
        }
    
        protected int getDefaultThemeToolbarColor3th() {
            return themeUtils.getDefaultThemeToolbarColor3th();
        }
    
        protected void updateRadioButtonColor(RadioButton radioButton) {
            themeUtils.updateRadioButtonColor(radioButton);
        }
    
        protected void setRadioTextButtonColor(RadioButton radioButton, int color) {
            themeUtils.setRadioTextButtonColor(radioButton, color);
        }
    
        public void updateSwitchColor(SwitchCompat sw, int color) {
            themeUtils.updateSwitchColor(sw, color);
        }
    
        public IconicsDrawable getToolbarIcon(IIcon icon) {
            return themeUtils.getToolbarIcon(icon);
        }
    
    
    }
    
    
    6. 所有Activity继承ThemeActivity设置主题。
    package cn.studyou.themedeep.ui;
    
    import android.content.DialogInterface;
    import android.os.Build;
    import android.support.v4.content.ContextCompat;
    import android.support.v7.app.AlertDialog;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.support.v7.widget.CardView;
    import android.support.v7.widget.SwitchCompat;
    import android.support.v7.widget.Toolbar;
    import android.view.View;
    import android.widget.Button;
    import android.widget.CompoundButton;
    import android.widget.ImageView;
    import android.widget.LinearLayout;
    import android.widget.ScrollView;
    import android.widget.TextView;
    
    import com.mikepenz.google_material_typeface_library.GoogleMaterial;
    
    import cn.studyou.themedeep.R;
    import cn.studyou.themedeep.base.ThemeActivity;
    import cn.studyou.themedeep.utils.ColorPaletteUtils;
    import cn.studyou.themedeep.utils.PreferenceUtils;
    import uz.shift.colorpicker.LineColorPicker;
    import uz.shift.colorpicker.OnColorChangedListener;
    
    public class SettingActivity extends ThemeActivity {
    
        private SwitchCompat swNavBar;
        private LinearLayout swNavBarStatus;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_setting);
            initView();
        }
    
        private Toolbar toolbar;
        private PreferenceUtils SP;
        private Button changeThemeButton;
        private TextView toolbarTitle;
        private SwitchCompat setTranslucentStatusBar;
        private LinearLayout translucentStatusBarStatus;
    
    
        private void initView() {
            SP = PreferenceUtils.getInstance(getApplicationContext());
            toolbar = (Toolbar) findViewById(R.id.toolbar);
            toolbarTitle = (TextView) findViewById(R.id.toolbar_title);
            setSupportActionBar(toolbar);
            changeThemeButton = (Button) findViewById(R.id.changeTheme);
            setTranslucentStatusBar = (SwitchCompat) findViewById(R.id.set_translucent_status_bar);
            translucentStatusBarStatus = (LinearLayout) findViewById(R.id.translucent_status_bar_status);
            swNavBar = (SwitchCompat) findViewById(R.id.set_colored_navBar);
            swNavBarStatus = (LinearLayout) findViewById(R.id.set_colored_navBar_status);
            changeThemeButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    primaryColorPiker();
                }
            });
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                translucentStatusBarStatus.setVisibility(View.VISIBLE);
                swNavBarStatus.setVisibility(View.VISIBLE);
            }
            setTranslucentStatusBar.setChecked(SP.getBoolean(getString(R.string.preference_translucent_status_bar), true));
            setTranslucentStatusBar.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    SP.putBoolean(getString(R.string.preference_translucent_status_bar), isChecked);
                    updateTheme();
                    setStatusBarColor();
                    updateSwitchColor(setTranslucentStatusBar, getAccentColor());
                }
            });
    
            toolbarTitle.setText(R.string.setting);
            toolbar.setNavigationIcon(getToolbarIcon(GoogleMaterial.Icon.gmd_arrow_back));
            toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    finish();
                }
            });
    
    
            swNavBar.setChecked(SP.getBoolean(getString(R.string.preference_colored_nav_bar), false));
            swNavBar.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    SP.putBoolean(getString(R.string.preference_colored_nav_bar), isChecked);
                    updateTheme();
                    updateSwitchColor(swNavBar, getAccentColor());
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        getWindow().setNavigationBarColor(isNavigationBarColored() ? getPrimaryColor() : ContextCompat.getColor(getApplicationContext(), R.color.md_black_1000));
                    }
                }
            });
        }
    
    
        private void primaryColorPiker() {
            final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this, getDialogStyle());
    
            final View dialogLayout = getLayoutInflater().inflate(R.layout.color_piker_primary, null);
            final LineColorPicker colorPicker = (LineColorPicker) dialogLayout.findViewById(R.id.color_picker_primary);
            final LineColorPicker colorPicker2 = (LineColorPicker) dialogLayout.findViewById(R.id.color_picker_primary_2);
            final TextView dialogTitle = (TextView) dialogLayout.findViewById(R.id.cp_primary_title);
            CardView dialogCardView = (CardView) dialogLayout.findViewById(R.id.cp_primary_card);
            dialogCardView.setCardBackgroundColor(getCardBackgroundColor());
    
            colorPicker.setColors(ColorPaletteUtils.getBaseColors(getApplicationContext()));
            for (int i : colorPicker.getColors())
                for (int i2 : ColorPaletteUtils.getColors(getBaseContext(), i))
                    if (i2 == getPrimaryColor()) {
                        colorPicker.setSelectedColor(i);
                        colorPicker2.setColors(ColorPaletteUtils.getColors(getBaseContext(), i));
                        colorPicker2.setSelectedColor(i2);
                        break;
                    }
    
            dialogTitle.setBackgroundColor(getPrimaryColor());
    
            colorPicker.setOnColorChangedListener(new OnColorChangedListener() {
                @Override
                public void onColorChanged(int c) {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        if (isTranslucentStatusBar()) {
                            getWindow().setStatusBarColor(ColorPaletteUtils.getObscuredColor(getPrimaryColor()));
                        } else getWindow().setStatusBarColor(c);
                    }
    
                    toolbar.setBackgroundColor(c);
                    dialogTitle.setBackgroundColor(c);
                    colorPicker2.setColors(ColorPaletteUtils.getColors(getApplicationContext(), colorPicker.getColor()));
                    colorPicker2.setSelectedColor(colorPicker.getColor());
                }
            });
            colorPicker2.setOnColorChangedListener(new OnColorChangedListener() {
                @Override
                public void onColorChanged(int c) {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        if (isTranslucentStatusBar()) {
                            getWindow().setStatusBarColor(ColorPaletteUtils.getObscuredColor(c));
                        } else getWindow().setStatusBarColor(c);
                        if (isNavigationBarColored())
                            getWindow().setNavigationBarColor(c);
                        else
                            getWindow().setNavigationBarColor(ContextCompat.getColor(getApplicationContext(), R.color.md_black_1000));
                    }
                    toolbar.setBackgroundColor(c);
                    dialogTitle.setBackgroundColor(c);
                }
            });
            dialogBuilder.setView(dialogLayout);
    
            dialogBuilder.setNeutralButton(getString(R.string.cancel).toUpperCase(), new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        if (isTranslucentStatusBar()) {
                            getWindow().setStatusBarColor(ColorPaletteUtils.getObscuredColor(getPrimaryColor()));
                        } else getWindow().setStatusBarColor(getPrimaryColor());
                    }
                    toolbar.setBackgroundColor(getPrimaryColor());
                    dialog.cancel();
                }
            });
    
            dialogBuilder.setPositiveButton(getString(R.string.ok_action).toUpperCase(), new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    SP.putInt(getString(R.string.preference_primary_color), colorPicker2.getColor());
                    updateTheme();
                    setNavBarColor();
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        if (isTranslucentStatusBar()) {
                            getWindow().setStatusBarColor(ColorPaletteUtils.getObscuredColor(getPrimaryColor()));
                        } else {
                            getWindow().setStatusBarColor(getPrimaryColor());
                        }
                    }
                }
            });
    
            dialogBuilder.setOnDismissListener(new DialogInterface.OnDismissListener() {
                @Override
                public void onDismiss(DialogInterface dialog) {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        if (isTranslucentStatusBar()) {
                            getWindow().setStatusBarColor(ColorPaletteUtils.getObscuredColor(getPrimaryColor()));
                        } else getWindow().setStatusBarColor(getPrimaryColor());
                        if (isNavigationBarColored())
                            getWindow().setNavigationBarColor(getPrimaryColor());
                        else
                            getWindow().setNavigationBarColor(ContextCompat.getColor(getApplicationContext(), R.color.md_black_1000));
                    }
                    toolbar.setBackgroundColor(getPrimaryColor());
    
                }
            });
            dialogBuilder.show();
        }
    
        @Override
        public void onResume() {
            super.onResume();
            updateNowTheme();
        }
    
        private void updateNowTheme() {
            toolbar.setPopupTheme(getPopupToolbarStyle());
            toolbar.setBackgroundColor(getPrimaryColor());
            toolbar.setTitle("");
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                if (isTranslucentStatusBar()) {
                    getWindow().setStatusBarColor(ColorPaletteUtils.getObscuredColor(getPrimaryColor()));
                } else {
                    getWindow().setStatusBarColor(getPrimaryColor());
                }
                getWindow().setNavigationBarColor(isNavigationBarColored() ? getPrimaryColor() : ContextCompat.getColor(getApplicationContext(), R.color.md_black_1000));
            }
        }
    }
    
    
    7. 选取主题颜色写到color.xml中供后续使用(更多颜色值见源码)。
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <!--Accent Color Collection-->
        <color name="accent_red">#f44336</color>
        <color name="accent_pink">#e91e63</color>
        <color name="accent_purple">#9c27b0</color>
        <color name="accent_deep_purple">#673ab7</color>
        <color name="accent_indago">#3f51b5</color>
        <color name="accent_blue">#2196f3</color>
        <color name="accent_cyan">#00bcd4</color>
        <color name="accent_teal">#009688</color>
        <color name="accent_green">#4caf50</color>
        <color name="accent_yellow">#ffeb3b</color>
        <color name="accent_amber">#ffc107</color>
        <color name="accent_orange">#ff9800</color>
        <color name="accent_brown">#795548</color>
        <color name="accent_white">#FFFFFF</color>
        <color name="accent_grey">#9e9e9e</color>
        <color name="accent_black">#000000</color>
    </resources>
    

    总结:

    • 阅读了LeafPic的源码,觉得主题切换真的很不错,就提炼出来,其实原理很简单,供做主题切换的同学借鉴。
    • 同时希望大家多阅读优秀的代码,提升自己。
    • 本文源码地址:ThemeDeep

    相关文章

      网友评论

      本文标题:Android 深入(二)- 利用ToolBar实现动态主题

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