Android更换主题
类似效果
简单写法 主题属性custom_theme_attrs.xml
-
-
<resources>
-
<!-- 自定义属性 -->
-
<attr name="text_color" format="color" />
-
-
<!-- 日间主题 -->
-
<style name="DayTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
-
<item name="text_color">@color/black_tx_color</item>
-
</style>
-
-
<!-- 夜间主题 -->
-
<style name="NightTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
-
<item name="text_color">@color/white_tx_color</item>
-
</style>
-
</resources>
颜色定义custom_theme_colors.xml
-
<resources>
-
<!-- 日间模式 -->
-
<color name="black_tx_color">#333333</color>
-
-
<!-- 夜间模式 -->
-
<color name="white_tx_color">#f0f0f0</color>
-
</resources>
布局
-
<LinearLayout
-
android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android"
-
xmlns:tools="http://schemas.android.com/tools"
-
android:id="@ id/root_view"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
>
-
-
-
<Button
-
android:id="@ id/change_btn"
-
android:layout_width="match_parent"
-
android:layout_height="wrap_content"
-
android:layout_marginTop="20dp"
-
android:text="给我改主题"
-
android:textColor="@color/black"
-
/>
-
-
<Button
-
android:textColor="@color/black"
-
android:id="@ id/second_btn"
-
android:layout_width="match_parent"
-
android:layout_height="wrap_content"
-
android:layout_below="@id/change_btn"
-
android:layout_marginTop="20dp"
-
android:text="Recyclerview"
-
/>
-
-
<TextView
-
android:id="@ id/tv_name"
-
android:layout_width="match_parent"
-
android:layout_height="wrap_content"
-
android:layout_marginTop="120dp"
-
android:gravity="center"
-
android:text="aaaaaaaa"
-
android:textColor="?attr/text_color"
-
android:textSize="20dp" />
-
-
-
-
</LinearLayout>
代码片段
-
//切换主题
-
public class MainActivity5 extends AppCompatActivity {
-
Button change_btn;
-
Button second_btn;
-
TextView tv_name;
-
private Colorful mColorful;
-
-
-
-
protected void onCreate(Bundle savedInstanceState) {
-
setTheme(R.style.DayTheme);
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_main);
-
change_btn = (Button) findViewById(R.id.change_btn);
-
second_btn = (Button) findViewById(R.id.second_btn);
-
tv_name = (TextView) findViewById(R.id.tv_name);
-
-
change_btn.setOnClickListener(new View.OnClickListener() {
-
-
public void onClick(View view) {
-
animChangeColor(R.style.NightTheme);
-
}
-
});
-
second_btn.setOnClickListener(new View.OnClickListener() {
-
-
public void onClick(View view) {
-
animChangeColor(R.style.DayTheme);
-
}
-
});
-
-
//Recyclerview
-
// ViewGroupSetter rvSetter = new ViewGroupSetter(mNightRv, R.attr.root_view_bg);
-
// rvSetter.childViewTextColor(R.id.category_desc, R.attr.one_text_bg);
-
// rvSetter.childViewTextColor(R.id.category_author, R.attr.two_text_bg);
-
// rvSetter.childViewTextColor(R.id.category_date, R.attr.two_text_bg);
-
// rvSetter.childViewBgColor(R.id.night_rl, R.attr.cardview_bg);
-
-
// 构建Colorful对象
-
mColorful = new Colorful.Builder(this)
-
.textColor(R.id.tv_name, R.attr.text_color) // 设置文本颜色
-
// .setter(rvSetter)
-
.create();
-
-
}
-
-
boolean isNight = false ;
-
-
// 切换主题
-
private void changeThemeWithColorful() {
-
if (!isNight) {
-
mColorful.setTheme(R.style.DayTheme);
-
} else {
-
mColorful.setTheme(R.style.NightTheme);
-
}
-
isNight = !isNight;
-
}
-
-
/**
-
* 给夜间模式增加一个动画,颜色渐变
-
*
-
* @param newTheme
-
*/
-
private void animChangeColor(final int newTheme) {
-
final View rootView = getWindow().getDecorView();
-
rootView.setDrawingCacheEnabled(true);
-
rootView.buildDrawingCache(true);
-
-
final Bitmap localBitmap = Bitmap.createBitmap(rootView.getDrawingCache());
-
rootView.setDrawingCacheEnabled(false);
-
if (null != localBitmap && rootView instanceof ViewGroup) {
-
final View tmpView = new View(this);
-
tmpView.setBackgroundDrawable(new BitmapDrawable(getResources(), localBitmap));
-
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup
-
.LayoutParams.MATCH_PARENT);
-
((ViewGroup) rootView).addView(tmpView, params);
-
tmpView.animate().alpha(0).setDuration(400).setListener(new Animator.AnimatorListener() {
-
-
public void onAnimationStart(Animator animation) {
-
mColorful.setTheme(newTheme);
-
System.gc();
-
}
-
-
-
public void onAnimationEnd(Animator animation) {
-
((ViewGroup) rootView).removeView(tmpView);
-
localBitmap.recycle();
-
}
-
-
-
public void onAnimationCancel(Animator animation) {
-
-
}
-
-
-
public void onAnimationRepeat(Animator animation) {
-
-
}
-
}).start();
-
}
-
}
-
-
private Disposable countdownDisposable;
-
-
-
protected void onDestroy() {
-
super.onDestroy();
-
countdownDisposable.dispose();
-
}
-
}
用到的工具 Colorful
-
public class Colorful
-
{
-
/**
-
* Colorful Builder
-
*/
-
Builder mBuilder;
-
-
/**
-
* private constructor
-
*
-
* @param builder
-
*/
-
private Colorful(Builder builder)
-
{
-
mBuilder = builder;
-
}
-
-
/**
-
* 设置新的主题
-
*
-
* @param newTheme
-
*/
-
public void setTheme(int newTheme)
-
{
-
mBuilder.setTheme(newTheme);
-
}
-
-
/**
-
* 构建Colorful的Builder对象
-
*
-
* @author mrsimple
-
*/
-
public static class Builder
-
{
-
/**
-
* 存储了视图和属性资源id的关系表
-
*/
-
List<ViewSetter> mElements = new ArrayList<>();
-
/**
-
* 目标Activity
-
*/
-
Activity mActivity;
-
-
/**
-
* @param activity
-
*/
-
public Builder(Activity activity)
-
{
-
mActivity = activity;
-
}
-
-
/**
-
* @param fragment
-
*/
-
public Builder(Fragment fragment)
-
{
-
mActivity = fragment.getActivity();
-
}
-
-
private View findViewById(int viewId)
-
{
-
return mActivity.findViewById(viewId);
-
}
-
-
/**
-
* 将View id与存储该view背景色的属性进行绑定
-
*
-
* @param viewId 控件id
-
* @param colorId 颜色属性id
-
* @return
-
*/
-
public Builder backgroundColor(int viewId, int colorId)
-
{
-
mElements.add(new ViewBackgroundColorSetter(findViewById(viewId), colorId));
-
return this;
-
}
-
-
/**
-
* 将View id与存储该view背景Drawable的属性进行绑定
-
*
-
* @param viewId 控件id
-
* @param drawableId Drawable属性id
-
* @return
-
*/
-
public Builder backgroundDrawable(int viewId, int drawableId)
-
{
-
mElements.add(new ViewBackgroundDrawableSetter(
-
findViewById(viewId), drawableId));
-
return this;
-
}
-
-
/**
-
* 将TextView id与存储该TextView文本颜色的属性进行绑定
-
*
-
* @param viewId TextView或者TextView子类控件的id
-
* @param colorId 颜色属性id
-
* @return
-
*/
-
public Builder textColor(int viewId, int colorId)
-
{
-
TextView textView = (TextView) findViewById(viewId);
-
mElements.add(new TextColorSetter(textView, colorId));
-
return this;
-
}
-
-
/**
-
* 用户手动构造并且添加Setter
-
*
-
* @param setter 用户自定义的Setter
-
* @return
-
*/
-
public Builder setter(ViewSetter setter)
-
{
-
mElements.add(setter);
-
return this;
-
}
-
-
/**
-
* 设置新的主题
-
*
-
* @param newTheme
-
*/
-
protected void setTheme(int newTheme)
-
{
-
mActivity.setTheme(newTheme);
-
makeChange(newTheme);
-
}
-
-
/**
-
* 修改各个视图绑定的属性
-
*/
-
private void makeChange(int themeId)
-
{
-
Theme curTheme = mActivity.getTheme();
-
for (ViewSetter setter : mElements)
-
{
-
setter.setValue(curTheme, themeId);
-
}
-
}
-
-
/**
-
* 创建Colorful对象
-
*
-
* @return
-
*/
-
public Colorful create()
-
{
-
return new Colorful(this);
-
}
-
}
-
}
RecyclerViewSetter
-
public class RecyclerViewSetter extends ViewGroupSetter
-
{
-
-
public RecyclerViewSetter(ViewGroup targetView, int resId)
-
{
-
super(targetView, resId);
-
}
-
-
public RecyclerViewSetter(ViewGroup targetView)
-
{
-
super(targetView);
-
}
-
-
-
protected void clearRecyclerViewRecyclerBin(View rootView)
-
{
-
super.clearRecyclerViewRecyclerBin(rootView);
-
((RecyclerView) rootView).getRecycledViewPool().clear();
-
}
-
-
}
TextColorSetter
-
public class TextColorSetter extends ViewSetter
-
{
-
public TextColorSetter(TextView textView, int resId)
-
{
-
super(textView, resId);
-
}
-
-
public TextColorSetter(int viewId, int resId)
-
{
-
super(viewId, resId);
-
}
-
-
-
public void setValue(Theme newTheme, int themeId)
-
{
-
if (mView == null)
-
{
-
return;
-
}
-
Log.e("color123", "setValue(TextColorSetter.java:29)");
-
((TextView) mView).setTextColor(getColor(newTheme));
-
}
-
}
ViewBackgroundColorSetter
-
public class ViewBackgroundColorSetter extends ViewSetter
-
{
-
public ViewBackgroundColorSetter(View target, int resId)
-
{
-
super(target, resId);
-
}
-
-
public ViewBackgroundColorSetter(int viewId, int resId)
-
{
-
super(viewId, resId);
-
}
-
-
-
public void setValue(Theme newTheme, int themeId)
-
{
-
if (mView != null)
-
{
-
Log.e("color123","setValue(ViewBackgroundColorSetter.java:29)");
-
mView.setBackgroundColor(getColor(newTheme));
-
}
-
}
-
}
ViewBackgroundDrawableSetter
-
public class ViewBackgroundDrawableSetter extends ViewSetter
-
{
-
public ViewBackgroundDrawableSetter(View targetView, int resId)
-
{
-
super(targetView, resId);
-
}
-
-
-
public ViewBackgroundDrawableSetter(int viewId, int resId)
-
{
-
super(viewId, resId);
-
}
-
-
-
-
public void setValue(Theme newTheme, int themeId)
-
{
-
if (mView == null)
-
{
-
return;
-
}
-
TypedArray a = newTheme.obtainStyledAttributes(themeId,
-
new int[]{mAttrResId});
-
int attributeResourceId = a.getResourceId(0, 0);
-
Drawable drawable = mView.getResources().getDrawable(
-
attributeResourceId);
-
a.recycle();
-
mView.setBackgroundDrawable(drawable);
-
}
-
}
ViewGroupSetter
-
public class ViewGroupSetter extends ViewSetter
-
{
-
/**
-
* ListView的子试图的Setter
-
*/
-
protected Set<ViewSetter> mItemViewSetters = new HashSet<ViewSetter>();
-
-
/**
-
* @param targetView
-
* @param resId
-
*/
-
public ViewGroupSetter(ViewGroup targetView, int resId)
-
{
-
super(targetView, resId);
-
}
-
-
public ViewGroupSetter(ViewGroup targetView)
-
{
-
super(targetView, 0);
-
}
-
-
/**
-
* 设置View的背景色
-
*
-
* @param viewId
-
* @param colorId
-
* @return
-
*/
-
public ViewGroupSetter childViewBgColor(int viewId, int colorId)
-
{
-
mItemViewSetters.add(new ViewBackgroundColorSetter(viewId, colorId));
-
return this;
-
}
-
-
/**
-
* 设置View的drawable背景
-
*
-
* @param viewId
-
* @param drawableId
-
* @return
-
*/
-
public ViewGroupSetter childViewBgDrawable(int viewId, int drawableId)
-
{
-
mItemViewSetters.add(new ViewBackgroundDrawableSetter(viewId,
-
drawableId));
-
return this;
-
}
-
-
/**
-
* 设置文本颜色,因此View的类型必须为TextView或者其子类
-
*
-
* @param viewId
-
* @param colorId
-
* @return
-
*/
-
public ViewGroupSetter childViewTextColor(int viewId, int colorId)
-
{
-
mItemViewSetters.add(new TextColorSetter(viewId, colorId));
-
return this;
-
}
-
-
-
public void setValue(Theme newTheme, int themeId)
-
{
-
mView.setBackgroundColor(getColor(newTheme));
-
// 清空AbsListView的元素
-
clearListViewRecyclerBin(mView);
-
// 清空RecyclerView
-
clearRecyclerViewRecyclerBin(mView);
-
// 修改所有子元素的相关属性
-
changeChildenAttrs((ViewGroup) mView, newTheme, themeId);
-
}
-
-
/**
-
* @param viewId
-
* @return
-
*/
-
private View findViewById(View rootView, int viewId)
-
{
-
View targetView = rootView.findViewById(viewId);
-
return targetView;
-
}
-
-
/**
-
* 修改子视图的对应属性
-
*
-
* @param viewGroup
-
* @param newTheme
-
* @param themeId
-
*/
-
private void changeChildenAttrs(ViewGroup viewGroup, Theme newTheme, int themeId)
-
{
-
int childCount = viewGroup.getChildCount();
-
//递归用法
-
for (int i = 0; i < childCount; i )
-
{
-
View childView = viewGroup.getChildAt(i);
-
// 深度遍历
-
if (childView instanceof ViewGroup)
-
{
-
changeChildenAttrs((ViewGroup) childView, newTheme, themeId);
-
}
-
-
// 遍历子元素与要修改的属性,如果相同那么则修改子View的属性
-
for (ViewSetter setter : mItemViewSetters)
-
{
-
// 每次都要从ViewGroup中查找数据
-
setter.mView = findViewById(viewGroup, setter.mViewId);
-
-
//因为viewgroup中的所有的id都添加进来了,而且每一个id都是独一无二的,
-
// 所以会有一个判断,当childView的id和setter中的id相等时,才会修改属性
-
if (childView.getId() == setter.getViewId())
-
{
-
setter.setValue(newTheme, themeId);
-
}
-
}
-
}
-
}
-
-
private void clearListViewRecyclerBin(View rootView)
-
{
-
if (rootView instanceof AbsListView)
-
{
-
try
-
{
-
-
Field localField = AbsListView.class.getDeclaredField("mRecycler");
-
localField.setAccessible(true);
-
Method localMethod = Class.forName(
-
"android.widget.AbsListView$RecycleBin")
-
.getDeclaredMethod("clear", new Class[0]);
-
localMethod.setAccessible(true);
-
localMethod.invoke(localField.get(rootView), new Object[0]);
-
Log.e("", "### 清空AbsListView的RecycerBin ");
-
} catch (NoSuchFieldException e1)
-
{
-
e1.printStackTrace();
-
} catch (ClassNotFoundException e2)
-
{
-
e2.printStackTrace();
-
} catch (NoSuchMethodException e3)
-
{
-
e3.printStackTrace();
-
} catch (IllegalAccessException e4)
-
{
-
e4.printStackTrace();
-
} catch (InvocationTargetException e5)
-
{
-
e5.printStackTrace();
-
}
-
}
-
}
-
-
protected void clearRecyclerViewRecyclerBin(View rootView)
-
{
-
if (rootView instanceof RecyclerView)
-
{
-
try
-
{
-
Field localField = RecyclerView.class
-
.getDeclaredField("mRecycler");
-
localField.setAccessible(true);
-
Method localMethod = Class.forName(
-
"android.support.v7.widget.RecyclerView$Recycler")
-
.getDeclaredMethod("clear", new Class[0]);
-
localMethod.setAccessible(true);
-
localMethod.invoke(localField.get(rootView), new Object[0]);
-
Log.e("", "### 清空RecyclerView的Recycer ");
-
rootView.invalidate();
-
((RecyclerView) rootView).getRecycledViewPool().clear();
-
} catch (NoSuchFieldException e1)
-
{
-
e1.printStackTrace();
-
} catch (ClassNotFoundException e2)
-
{
-
e2.printStackTrace();
-
} catch (NoSuchMethodException e3)
-
{
-
e3.printStackTrace();
-
} catch (IllegalAccessException e4)
-
{
-
e4.printStackTrace();
-
} catch (InvocationTargetException e5)
-
{
-
e5.printStackTrace();
-
}
-
}
-
}
-
}
ViewSetter
-
public abstract class ViewSetter
-
{
-
/**
-
* 目标View
-
*/
-
protected View mView;
-
/**
-
* 目标view id,有时在初始化时还未构建该视图,比如ListView的Item View中的某个控件
-
*/
-
protected int mViewId;
-
/**
-
* 目标View要的特定属性id
-
*/
-
protected int mAttrResId;
-
-
public ViewSetter(View targetView, int resId)
-
{
-
mView = targetView;
-
mAttrResId = resId;
-
}
-
-
public ViewSetter(int viewId, int resId)
-
{
-
mViewId = viewId;
-
mAttrResId = resId;
-
}
-
-
/**
-
* @param newTheme
-
* @param themeId
-
*/
-
public abstract void setValue(Theme newTheme, int themeId);
-
-
/**
-
* 获取视图的Id
-
*
-
* @return
-
*/
-
protected int getViewId()
-
{
-
return mView != null ? mView.getId() : -1;
-
}
-
-
protected boolean isViewNotFound()
-
{
-
return mView == null;
-
}
-
-
/**
-
* @param newTheme
-
* @return
-
*/
-
protected int getColor(Theme newTheme)
-
{
-
//返回重新指定后的资源id
-
TypedValue typedValue = new TypedValue();
-
newTheme.resolveAttribute(mAttrResId, typedValue, true);
-
return typedValue.data;
-
}
-
}
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgfaigc
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01