首先來個最簡單的一鍵切換主題功能,就作個白天和晚上的主題好了。java
先看咱們的styles文件:android
1 <resources> 2 3 <!-- Base application theme. --> 4 <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> 5 <!-- Customize your theme here. --> 6 <item name="colorPrimary">@color/colorPrimary</item> 7 <item name="colorPrimaryDark">@color/colorPrimaryDark</item> 8 <item name="colorAccent">@color/colorAccent</item> 9 </style> 10 <style name="AppTheme.NoActionBar"> 11 <item name="windowActionBar">false</item> 12 <item name="windowNoTitle">true</item> 13 </style> 14 <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" /> 15 <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" /> 16 17 <!--白天主題--> 18 <style name="dayTheme" parent="AppTheme"> 19 <item name="android:textColor">#525252</item> 20 <item name="android:background">#f7f7f7</item> 21 </style> 22 23 <!--夜間主題--> 24 <style name="nightTheme" parent="AppTheme"> 25 <item name="android:textColor">#868a96</item> 26 <item name="android:background">#1e1e2a </item> 27 </style> 28 29 30 </resources>
好,而後咱們來看看主要activity緩存
package com.example.administrator.mainchangethemeapp; import android.content.SharedPreferences; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.View; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { //sputils是對SharedPreferences的封裝,代碼就不上了,你們理解意思就好了 if(SPUtils.get(this,"theme","dayTheme").equals("dayTheme")) { //默認是白天主題 setTheme(R.style.dayTheme); }else { //不然是晚上主題 setTheme(R.style.nightTheme); } super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv=(TextView)this.findViewById(R.id.tv); tv.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { if(SPUtils.get(MainActivity.this,"theme","dayTheme").equals("dayTheme")) { SPUtils.put(MainActivity.this,"theme","nightTheme"); }else { SPUtils.put(MainActivity.this, "theme", "dayTheme"); } recreate(); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
而後來看下效果:app
固然了,上面這個demo其實是有缺陷的。有人會說了 你看人家新浪微博,那麼多主題,你要是用這種方法,你這個app得有多大,ide
能作成微博那樣要用什麼就去下載什麼麼?答案是能夠的。其實方案也很簡單。佈局
這種方案的思路就是,把主題包 額外作成一個apk,注意這個apk 是不會在桌面顯示的。你只能在設置裏的app列表裏找到他。字體
而後在你的主activity裏 取這個apk裏的資源 便可。這裏我也把這種方案的代碼寫一遍。注意下載apk 安裝apk的代碼我就不寫了。動畫
咱們就假設 咱們要切換的主題就是系統自帶的主題就好了,咱們的主activity 使用的是白天主題。而後咱們的子app裏面ui
爲了簡化代碼,咱們就不放自定義主題了,就使用android studio 原始的代碼,一步步來,this
先放上子app裏的styles文件,其實這個裏面一行代碼都沒更改,全是ide本身生成的:
1 <resources> 2 3 <!-- Base application theme. --> 4 <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> 5 <!-- Customize your theme here. --> 6 <item name="colorPrimary">@color/colorPrimary</item> 7 <item name="colorPrimaryDark">@color/colorPrimaryDark</item> 8 <item name="colorAccent">@color/colorAccent</item> 9 </style> 10 <style name="AppTheme.NoActionBar"> 11 <item name="windowActionBar">false</item> 12 <item name="windowNoTitle">true</item> 13 </style> 14 <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" /> 15 <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" /> 16 17 18 </resources>
而後就是子activity裏的 配置文件manifest:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.administrator.sonproject" > <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" android:theme="@style/AppTheme.NoActionBar" > <intent-filter> <action android:name="android.intent.action.MAIN" /> </intent-filter> </activity> </application> </manifest>
注意這裏
<category android:name="android.intent.category.LAUNCHER" />
的這行代碼 我是沒寫的。這樣就是保證在這個apk 安裝好之後不會在桌面出現。
而後咱們來看看主activity代碼
1 package com.example.administrator.mainchangethemeapp; 2 3 import android.content.Context; 4 import android.content.SharedPreferences; 5 import android.content.pm.PackageManager; 6 import android.content.res.TypedArray; 7 import android.os.Bundle; 8 import android.support.design.widget.FloatingActionButton; 9 import android.support.design.widget.Snackbar; 10 import android.support.v4.app.Fragment; 11 import android.support.v7.app.AppCompatActivity; 12 import android.support.v7.widget.Toolbar; 13 import android.util.Log; 14 import android.util.TypedValue; 15 import android.view.View; 16 import android.view.Menu; 17 import android.view.MenuItem; 18 import android.widget.TextView; 19 20 public class MainActivity extends AppCompatActivity { 21 22 private TextView tv; 23 24 @Override 25 protected void onCreate(Bundle savedInstanceState) { 26 //sputils是對SharedPreferences的封裝,代碼就不上了,你們理解意思就好了 27 if (SPUtils.get(this, "theme", "dayTheme").equals("dayTheme")) { 28 //默認是白天主題 29 setTheme(R.style.dayTheme); 30 } else { 31 //不然是晚上主題,這裡晚上主題我們就去加載我們晚上主題apk裏的資源 32 int resourceId = getResourceId(getPackageContext(this, "com.example.administrator.sonproject"), "style", "AppTheme"); 33 setTheme(resourceId); 34 } 35 super.onCreate(savedInstanceState); 36 setContentView(R.layout.activity_main); 37 tv = (TextView) this.findViewById(R.id.tv); 38 tv.setOnClickListener(new View.OnClickListener() { 39 40 @Override 41 public void onClick(View v) { 42 if (SPUtils.get(MainActivity.this, "theme", "dayTheme").equals("dayTheme")) { 43 SPUtils.put(MainActivity.this, "theme", "nightTheme"); 44 } else { 45 SPUtils.put(MainActivity.this, "theme", "dayTheme"); 46 } 47 recreate(); 48 } 49 }); 50 } 51 52 @Override 53 public boolean onCreateOptionsMenu(Menu menu) { 54 // Inflate the menu; this adds items to the action bar if it is present. 55 getMenuInflater().inflate(R.menu.menu_main, menu); 56 return true; 57 } 58 59 @Override 60 public boolean onOptionsItemSelected(MenuItem item) { 61 // Handle action bar item clicks here. The action bar will 62 // automatically handle clicks on the Home/Up button, so long 63 // as you specify a parent activity in AndroidManifest.xml. 64 int id = item.getItemId(); 65 66 //noinspection SimplifiableIfStatement 67 if (id == R.id.action_settings) { 68 return true; 69 } 70 71 return super.onOptionsItemSelected(item); 72 } 73 74 75 /** 76 * 獲取其餘apk的context 77 * @param context 78 * @param packageName 79 * @return 80 */ 81 public static Context getPackageContext(Context context, String packageName) { 82 try { 83 return context.createPackageContext(packageName, Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); 84 } catch (PackageManager.NameNotFoundException e) { 85 e.printStackTrace(); 86 } 87 return null; 88 } 89 90 //獲取指定context的 type裏面的 name屬性 91 public static int getResourceId(Context context, String type, String name) { 92 return context.getResources().getIdentifier(name, type, context.getPackageName()); 93 } 94 }
你看,到這裏 咱們就實現了,動態加載主題的方式了。固然了,到這裏依舊是不完美的,由於settheme方法你們都知道必定要重啓activity纔有效啊。這樣就很差了。
體驗並不是最佳。老是給人很突兀的感受。並且咱們都知道重啓activity的成本很大。要考慮不少生命週期之類的東西。那咱們繼續往下看,看看有什麼比較好的解決方案能解決這個問題。
首先 咱們能夠考慮一下這個問題,所謂的切換主題 之類的,無非就是把你那些控件的 背景色啊 字體顏色之類的 改變了一下。對於一個app來講,用戶通常只有一個界面 會有切換主題的這個入口,
換句話說,咱們的app裏面 只有這一個activity 須要實現 不重啓activity就切換 控件style的功能,其餘activity咱們是不須要實現這個功能的,由於再切換過去的時候基本上都會走oncreate。因此
咱們只須要考慮這個 有切換主題按鈕的 這個activity能實現 不重啓activity就換皮膚的功能就能夠了。其餘activity不須要考慮。so 這樣一想 這個功能就簡單清晰了不少。
首先咱們能夠自定義2個屬性,咱們把他放在attrs 這個xml裏面
1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 <!-- 首先自定義屬性,這裏咱們爲了簡便 只自定義了這2種屬性,若是你要本身作的話 看需求能夠增長屬性--> 4 <!-- 另外注意咱們這裏並無使用declare-styleable 來包裹這裏的2個屬性 好處就是在xml文件裏 不用另外定義前綴了--> 5 <attr name="custom_background" format="reference|color"/> 6 <attr name="custom_textcolor" format="reference|color"/> 7 </resources>
而後咱們去定義一下咱們的主題:
1 <resources> 2 3 <!-- 這裏就設置2個最簡單的 主題就好了,--> 4 <!--白天主題--> 5 <style name="dayTheme" > 6 <item name="custom_background">#f7f7f7</item> 7 <item name="custom_textcolor">#525252</item> 8 </style> 9 10 <!--晚上主題--> 11 <style name="nightTheme"> 12 <item name="custom_background">#1e1e2a</item> 13 <item name="custom_textcolor">#868a96</item> 14 </style> 15 </resources>
而後咱們來寫一下mainactivity的xml佈局文件,咱們假設這個佈局是很是簡單的:
1 <?xml version="1.0" encoding="utf-8"?> 2 <com.example.administrator.mainchangethemeapp.ThemeRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:background="?attr/custom_background" 6 android:id="@+id/mainview" 7 > 8 9 <com.example.administrator.mainchangethemeapp.ThemeTextView 10 android:id="@+id/tv" 11 android:layout_width="100dp" 12 android:layout_height="100dp" 13 android:layout_centerInParent="true" 14 android:text="一鍵切換主題" 15 android:background="?attr/custom_background" 16 android:textColor="?attr/custom_textcolor" 17 /> 18 19 </com.example.administrator.mainchangethemeapp.ThemeRelativeLayout>
你看這個佈局裏面 就一個relativelayout和一個textview。 和之前xml惟一的區別就是這裏backaground和textcolor使用的值 是咱們前面定義好的屬性了(可是要注意 這屬性是沒有值的 賦值的操做放在java代碼裏實現)。同時這2個控件 也並不是是系統控件 而是自定義控件。而後咱們看看這個自定義控件是怎麼寫的。注意我這裏就作了2個自定義控件,若是大家的那個切換主題的入口頁面裏面有其餘控件的話,就要學着下面的方法 本身拓展一下了,其實也很簡單的。
首先呢,咱們來定義一個接口,誰實現了這個接口 就說明這個控件能夠不啓動activity直接換膚!
1 package com.example.administrator.mainchangethemeapp; 2 3 import android.content.res.Resources; 4 import android.view.View; 5 6 /** 7 * Created by Administrator on 2015/11/14. 8 */ 9 public interface ThemeUIInterface { 10 11 public View getView(); 12 public void setTheme(Resources.Theme themeId); 13 }
而後咱們來看看2個自定義控件怎麼寫:
1 package com.example.administrator.mainchangethemeapp; 2 3 import android.content.Context; 4 import android.content.res.Resources; 5 import android.util.AttributeSet; 6 import android.util.Log; 7 import android.view.View; 8 import android.widget.RelativeLayout; 9 10 /** 11 * Created by Administrator on 2015/11/14. 12 */ 13 public class ThemeRelativeLayout extends RelativeLayout implements ThemeUIInterface{ 14 15 private int attr_background = -1; 16 17 public ThemeRelativeLayout(Context context) { 18 super(context); 19 } 20 21 public ThemeRelativeLayout(Context context, AttributeSet attrs) { 22 super(context, attrs); 23 this.attr_background =ViewAttributeUtil.getBackgroundAttibute(attrs); 24 } 25 26 public ThemeRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) { 27 super(context, attrs, defStyleAttr); 28 this.attr_background =ViewAttributeUtil.getBackgroundAttibute(attrs); 29 30 } 31 32 33 @Override 34 public View getView() { 35 return this; 36 } 37 38 @Override 39 public void setTheme(Resources.Theme themeId) { 40 if(attr_background!=-1) { 41 ViewAttributeUtil.applyBackgroundDrawable(this, themeId, attr_background); 42 } 43 } 44 }
1 package com.example.administrator.mainchangethemeapp; 2 3 import android.content.Context; 4 import android.content.res.Resources; 5 import android.util.AttributeSet; 6 import android.view.View; 7 import android.widget.TextView; 8 9 /** 10 * Created by Administrator on 2015/11/16. 11 */ 12 public class ThemeTextView extends TextView implements ThemeUIInterface{ 13 14 private int attr_drawable=-1; 15 private int attr_textColor=-1; 16 17 public ThemeTextView(Context context) { 18 super(context); 19 } 20 21 public ThemeTextView(Context context, AttributeSet attrs) { 22 super(context, attrs); 23 this.attr_drawable = ViewAttributeUtil.getBackgroundAttibute(attrs); 24 this.attr_textColor = ViewAttributeUtil.getTextColorAttribute(attrs); 25 } 26 27 public ThemeTextView(Context context, AttributeSet attrs, int defStyleAttr) { 28 super(context, attrs, defStyleAttr); 29 this.attr_drawable = ViewAttributeUtil.getBackgroundAttibute(attrs); 30 this.attr_textColor = ViewAttributeUtil.getTextColorAttribute(attrs); 31 } 32 33 @Override 34 public View getView() { 35 return this; 36 } 37 38 @Override 39 public void setTheme(Resources.Theme themeId) { 40 if (attr_drawable != -1) { 41 ViewAttributeUtil.applyBackgroundDrawable(this, themeId, attr_drawable); 42 } 43 if (attr_textColor != -1) { 44 ViewAttributeUtil.applyTextColor(this, themeId, attr_textColor); 45 } 46 } 47 }
看上去 其實也蠻簡單的對吧,無非就相比傳統控件,他對外暴露了 setTheme這個方法罷了,而這個setTheme方法 其實就作了一件事,調用系統本身的方法從新set那些屬性罷了。
1 package com.example.administrator.mainchangethemeapp; 2 3 4 import android.content.res.Resources; 5 import android.content.res.TypedArray; 6 import android.graphics.drawable.Drawable; 7 import android.util.AttributeSet; 8 import android.util.Log; 9 import android.widget.ImageView; 10 import android.widget.TextView; 11 12 public class ViewAttributeUtil { 13 14 public static int getAttributeValue(AttributeSet attr, int paramInt) { 15 int value = -1; 16 int count = attr.getAttributeCount(); 17 for(int i = 0; i <count;i++) { 18 if(attr.getAttributeNameResource(i) == paramInt) { 19 String str = attr.getAttributeValue(i); 20 if(null != str && str.startsWith("?")) { 21 value = Integer.valueOf(str.substring(1, str.length())).intValue(); 22 return value; 23 } 24 } 25 } 26 return value; 27 } 28 29 public static int getBackgroundAttibute(AttributeSet attr) { 30 return getAttributeValue(attr , android.R.attr.background); 31 } 32 33 34 public static int getTextColorAttribute(AttributeSet attr) { 35 return getAttributeValue(attr, android.R.attr.textColor); 36 } 37 38 public static void applyBackgroundDrawable(ThemeUIInterface ci, Resources.Theme theme, int paramInt) { 39 TypedArray ta = theme.obtainStyledAttributes(new int[]{paramInt}); 40 Drawable drawable = ta.getDrawable(0); 41 if(null != ci) { 42 (ci.getView()).setBackgroundDrawable(drawable); 43 } 44 ta.recycle(); 45 } 46 public static void applyTextColor(ThemeUIInterface ci, Resources.Theme theme, int paramInt) { 47 TypedArray ta = theme.obtainStyledAttributes(new int[]{paramInt}); 48 int resourceId = ta.getColor(0,0); 49 if(null != ci && ci instanceof TextView) { 50 ((TextView)ci.getView()).setTextColor(resourceId); 51 } 52 ta.recycle(); 53 } 54 55 }
好,到這裏 脈絡就逐漸清晰了,咱們就看看主activity裏怎麼寫了:
1 package com.example.administrator.mainchangethemeapp; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.view.Menu; 6 import android.view.MenuItem; 7 import android.view.View; 8 import android.widget.TextView; 9 10 public class MainActivity extends Activity { 11 12 private TextView tv; 13 14 private View view; 15 16 @Override 17 protected void onCreate(Bundle savedInstanceState) { 18 //這行代碼千萬不能漏掉,不然會報錯的。由於你在xml裏 的那些值 根本就沒有實際的值,若是不在這裏強制性的setTheme就直接報錯了 19 //在實際使用中 咱們固然能夠把這個方法 放在baseactivity裏面。咱們這裏默認主題就白天吧 20 setTheme(R.style.dayTheme); 21 super.onCreate(savedInstanceState); 22 setContentView(R.layout.activity_main); 23 //這個就是跟佈局 24 view = this.findViewById(R.id.mainview); 25 tv = (TextView) this.findViewById(R.id.tv); 26 tv.setOnClickListener(new View.OnClickListener() { 27 28 @Override 29 public void onClick(View v) { 30 31 //這邊邏輯沒啥好說的 其實能夠不須要看啊,就是白天就切換到黑夜 黑夜就切換到白天唄 32 if (SPUtils.get(MainActivity.this, "theme", "dayTheme").equals("dayTheme")) { 33 SPUtils.put(MainActivity.this, "theme", "nightTheme"); 34 setTheme(R.style.nightTheme); 35 } else { 36 SPUtils.put(MainActivity.this, "theme", "dayTheme"); 37 setTheme(R.style.dayTheme); 38 } 39 //這個方法就是實現不重啓頁面切換主題的 40 ThemeUiUtil.changeTheme(view, getTheme()); 41 } 42 }); 43 } 44 45 @Override 46 public boolean onCreateOptionsMenu(Menu menu) { 47 // Inflate the menu; this adds items to the action bar if it is present. 48 getMenuInflater().inflate(R.menu.menu_main, menu); 49 return true; 50 } 51 52 @Override 53 public boolean onOptionsItemSelected(MenuItem item) { 54 // Handle action bar item clicks here. The action bar will 55 // automatically handle clicks on the Home/Up button, so long 56 // as you specify a parent activity in AndroidManifest.xml. 57 int id = item.getItemId(); 58 59 //noinspection SimplifiableIfStatement 60 if (id == R.id.action_settings) { 61 return true; 62 } 63 64 return super.onOptionsItemSelected(item); 65 } 66 67 }
而後看一下切換主題的方法是怎麼作的:
1 package com.example.administrator.mainchangethemeapp; 2 3 import android.content.res.Resources; 4 import android.util.Log; 5 import android.view.View; 6 import android.view.ViewGroup; 7 import android.widget.AbsListView; 8 9 import java.lang.reflect.Field; 10 import java.lang.reflect.InvocationTargetException; 11 import java.lang.reflect.Method; 12 13 /** 14 * Created by Administrator on 2015/11/14. 15 */ 16 public class ThemeUiUtil { 17 /** 18 * 切換應用主題 19 * 20 * @param rootView 21 */ 22 public static void changeTheme(View rootView, Resources.Theme theme) { 23 //這裡邏輯很簡單 就是遞歸調用changeTheme-----遞歸調用setTheme了。 24 //注意 大家若是是listview也包含在裏面的話 listview自定義實現接口的時候要稍微複雜一些,看大家須要不須要也刷新listview裏的item了 25 //這裏爲了簡單 我就不寫那麼複雜了,就這一個邏輯:先set本身的theme 而後遍歷本身的子控件 逐一set 26 if (rootView instanceof ThemeUIInterface) { 27 ((ThemeUIInterface) rootView).setTheme(theme); 28 if (rootView instanceof ViewGroup) { 29 int count = ((ViewGroup) rootView).getChildCount(); 30 for (int i = 0; i < count; i++) { 31 changeTheme(((ViewGroup) rootView).getChildAt(i), theme); 32 } 33 } 34 } 35 } 36 37 38 }
你看,到這裏 咱們不重啓activity實現換膚的功能就基本實現了,固然要作的完美的話 還須要各位本身擴充一下 其餘控件。可是思路都是同樣的。
看到這裏 有人仍然會說,你這個雖然沒有重啓activity,可是仍是很差看呀,仍是顯的突兀了,可否作到知乎 android app那樣 切換白天黑夜主題的時候 顯的很柔順呢。
答案是能夠的,並且解決方案也比較簡單。就是給個動畫就完事了,在切換前 先保留一下 以前界面的bitmap 而後切換皮膚的的時候 把這個bitmap 顯示出來之後 而後改變他的
alpha值 就能夠了,當所有動畫顯示結束之後 把那些不須要的資源所有釋放 就ok了!
來看下代碼,這裏就放出點擊事件的代碼了,其餘地方與前面的代碼一致:
1 { 2 3 //咱們先取這個根佈局的 bitmap緩存 這個實際上跟截屏是差很少的一個東西。 4 view.setDrawingCacheEnabled(true); 5 view.buildDrawingCache(true); 6 final Bitmap localBitmap = Bitmap.createBitmap(view.getDrawingCache()); 7 view.setDrawingCacheEnabled(false); 8 9 //這邊邏輯沒啥好說的 其實能夠不須要看啊,就是白天就切換到黑夜 黑夜就切換到白天唄 10 if (SPUtils.get(MainActivity.this, "theme", "dayTheme").equals("dayTheme")) { 11 SPUtils.put(MainActivity.this, "theme", "nightTheme"); 12 setTheme(R.style.nightTheme); 13 } else { 14 SPUtils.put(MainActivity.this, "theme", "dayTheme"); 15 setTheme(R.style.dayTheme); 16 } 17 //咱們new出來的這個蒙版view --mengbanview 就把他放到跟佈局view裏面 而且讓他充滿 同時這個view的background就是截屏前咱們的那個截圖bitmap 18 final View mengbanView = new View(getApplicationContext()); 19 mengbanView.setBackgroundDrawable(new BitmapDrawable(getResources(), localBitmap)); 20 ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 21 ((ViewGroup) view).addView(mengbanView, params); 22 mengbanView.animate().alpha(0).setDuration(400).setListener(new Animator.AnimatorListener() { 23 @Override 24 public void onAnimationStart(Animator animation) { 25 //這個方法就是實現不重啓頁面切換主題的 26 ThemeUiUtil.changeTheme(view, getTheme()); 27 } 28 29 @Override 30 public void onAnimationEnd(Animator animation) { 31 //動畫結束的時候移出這個蒙版view 並釋放bitmap 32 ((ViewGroup) view).removeView(mengbanView); 33 localBitmap.recycle(); 34 } 35 36 @Override 37 public void onAnimationCancel(Animator animation) { 38 39 } 40 41 @Override 42 public void onAnimationRepeat(Animator animation) { 43 44 } 45 }).start(); 46 47 48 }
最後來看下效果是否和知乎同樣:
大功告成,看上去天然多了!