編輯:關於Android編程
智能手機的迅速普及,大大的豐富了我們的娛樂生活。現在大家都喜歡晚上睡覺前玩會兒手機,但是應用的日間模式往往亮度太大,對眼睛有較為嚴重的傷害。因此,如今的應用往往開發了 日間和夜間 兩種模式供用戶切換使用,那日間和夜間模式切換究竟是怎樣實現的呢?
在文字類的App上面基本上都會涉及到夜間模式、就是能夠根據不同的設定、呈現不同風格的界面給用戶、而且晚上看著不傷眼睛、實現方式也就是所謂的換膚(主題切換)、對於夜間模式的實現網上流傳了很多種方式、這裡先分享一個方法給大家、通過設置背景為透明的方法、降低屏幕的亮度與色度。
夜間模式代碼
public void night() { WindowManager.LayoutParams params = new WindowManager.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, LayoutParams.TYPE_APPLICATION, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT); params.gravity=Gravity.BOTTOM; params.y=10; if(myView==null){ myView=new TextView(this); myView.setBackgroundColor(0x80000000); } mWindowManager.addView(myView, params); Editor edit = skinSp.edit(); edit.putString("skin", NIGHT); edit.commit(); }
白天模式
public void day(){ if(myView!=null){ mWindowManager.removeView(myView); Editor edit = skinSp.edit(); edit.putString("skin", DAY); edit.commit(); } }
下面通過實例操作來詳細展示如何進行Android主題切換中的白天/夜間模式。
上述兩幅圖片,正是兩款App的夜間模式效果,所以,依據這個功能,來看看切換主題到底是怎麼實現的(當然現在github有好多PluginTheme開源插件,很多時候可以使用這些插件,不過我並不想講怎麼用那些插件,正所謂會用輪子還不如會造輪子)。
關於更換主題和換膚
這裡提到是做換主題功能,當然與之類似的就是換膚,換膚現在比較流行的是采用插件化動態加載技術來實現的,這樣可以起到熱插拔作用,需要皮膚時候用戶自主的在網上下載便是了,不用皮膚時便刪了皮膚插件包而不會影響宿主App的功能,這樣就不必把一大堆皮膚圖片放在本地而增加apk的大小,關於用插件化實現換膚功能這僅僅是插件化技術的冰山一角,關於插件化技術更多的作用,可以看看360前兩天開源的 DroidPlugin插件框架、OpenAltas框架、還有主席的DL框架。
好了,言歸正傳,現在我們需要實現的是主題切換功能,關於主題切換其實是切換整個App的顏色風格、排版風格、字體風格等,其中並不會有過多的圖片資源的切換,如有過多的圖片的更換那就是換膚的功能了。
現在我們要實現夜間/白天模式的切換功能,如下效果圖:
可以看到上面的效果正是夜間和白天兩種模式的切換功能,切換至夜間模式時整個App的背景色、字體顏色、按鈕顏色、標題欄顏色等全部需要切為夜間模式的顏色,當切回白天模式又切回原來的顏色,來看看怎麼做的?
實現主題切換
首先就是需要在app中准備兩套主題:
白天主題
<resources> <style name="DayTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">#03A9F4</item> <item name="android:textColorPrimary">#ffffff</item> <item name="android:windowBackground">@color/background_material_light</item> <item name="colorAccent">#00BCD4</item> <item name="colorControlNormal">#00BCD4</item> <item name="titleStyle">@style/DayTitleStyle</item> <item name="contentStyle">@style/DayContentStyle</item> <item name="buttonBg">#2196F3</item> <item name="buttonTextColor">#ffffff</item> <item name="checkTextColor">#2196F3</item> <item name="switchTextColor">#2196F3</item> </style> <style name="DayTitleStyle"> <item name="android:textColor">#212121</item> <item name="android:textSize">20sp</item> <item name="android:layout_margin">8dp</item> </style> <style name="DayContentStyle"> <item name="android:textColor">#9C27B0</item> <item name="android:textSize">16sp</item> <item name="android:layout_margin">16dp</item> <item name="android:maxLines">10</item> </style> </resources>
夜間主題
<resources> <style name="NightTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">#00796B</item> <item name="android:textColorPrimary">#212121</item> <item name="android:windowBackground">@color/background_material_dark</item> <item name="colorAccent">#00796B</item> <item name="colorControlNormal">#212121</item> <item name="titleStyle">@style/NightTitleStyle</item> <item name="contentStyle">@style/NightContentStyle</item> <item name="buttonBg">#00796B</item> <item name="buttonTextColor">#9E9E9E</item> <item name="checkTextColor">#212121</item> <item name="switchTextColor">#212121</item> </style> <style name="NightTitleStyle"> <item name="android:textColor">#212121</item> <item name="android:textSize">20sp</item> <item name="android:layout_margin">8dp</item> </style> <style name="NightContentStyle"> <item name="android:textColor">#212121</item> <item name="android:textSize">16sp</item> <item name="android:layout_margin">16dp</item> <item name="android:maxLines">10</item> </style> </resources>
上面這兩套主題中,各個屬性定義完全一模一樣,不一樣的只是屬性的值,其中在DayTheme和NightTheme的style中有這麼一段代碼:
<item name="titleStyle">@style/DayTitleStyle</item> <item name="contentStyle">@style/DayContentStyle</item> <item name="buttonBg">#2196F3</item> <item name="buttonTextColor">#ffffff</item> <item name="checkTextColor">#2196F3</item> <item name="switchTextColor">#2196F3</item>
正常情況下style中是不存在這些屬性的,它們這些是自定義屬性,主要是用來控制某些控件或者布局的屬性,它們的定義在attr文件中:
<?xml version="1.0" encoding="utf-8"?> <resources> <attr name="contentStyle" format="reference"/> <attr name="titleStyle" format="reference"/> <attr name="buttonBg" format="reference|color"/> <attr name="buttonTextColor" format="reference|color"/> <attr name="checkTextColor" format="reference|color"/> <attr name="switchTextColor" format="reference|color"/> </resources>
然後在布局中引用即可:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/title" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="CheckBox" android:textColor="?attr/checkTextColor" /> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="CheckBox" android:textColor="?attr/checkTextColor" /> <Switch android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Switch" android:textColor="?attr/switchTextColor" /> <Button android:id="@+id/btn_setting" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="設置" android:background="?attr/buttonBg" android:textColor="?attr/buttonTextColor" /> </LinearLayout>
最後在整個App主題的style中使用它們就ok了。這樣做有什麼好處呢?我們都知道App設置主題時候都是設置一個style,而App中某些控件或者布局的背景或者style樣式需要和整個主題樣式不同時,這時候可以通過設置個自定義屬性,通過在App的style中給與自定義屬性不同的值來達到目的。
切換主題
好了,有了兩套主題了,接下來是通過代碼來進行控制主題間的切換了,控制主題的切換其實就是通過setTheme(R.style.*);來設置不同的style從而達到界面風格的變換,不過這個方法setTheme()只在setContentView()方法前設置才有效,所以如果你想在其它地方調用這個方法來切換主題那是肯定不行的,所以這裡有兩個難點?
1、怎麼處理當前的設置界面在切換主題後同時切換主題風格
2、怎麼處理之前已經打開的界面讓他們切換主題風格
這裡我給出的答案是:
1、在當前切換主題的設置界面使用Activity.recreate()方法,該方法的作用就是當當前Activity的配置發生變化時,調用這個方法可以把當前Activity實例銷毀並重新創建出一個Activity實例。如此可見通過這個方法可以很容易的解決問題一,因為它會重新創建一個新的Activity實例。
2、這裡我使用的方法是通過設置Intent的Flag來達到更新之前Activity的效果,通過設置mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);讓它清除之前的Activity再創建一個新的Activity,這樣當返回之前的界面就可以更新主題了。【注】如果有多個界面可以通過設置主界面MainActivity的launchMode為singleTask,在返回主界面時候清除其它界面來更新主題
對於上面的方法(如有更好的方法歡迎告知,萬分感謝!)
代碼實現
最後再貼下代碼:
通過一個主題設置工具類設置主題,在每個Activity的setContentView()方法之前設置主題:
設置主題工具類:
public class ThemeChangeUtil { public static boolean isChange = false; public static void changeTheme(Activity activity){ if(isChange){ activity.setTheme(R.style.NightTheme); } } }
設置界面:
public class ChangeTheme extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { ThemeChangeUtil.changeTheme(this); super.onCreate(savedInstanceState); setContentView(R.layout.activity_change); Button mChangeBtn = (Button) findViewById(R.id.btn_change); mChangeBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (ThemeChangeUtil.isChange) { ThemeChangeUtil.isChange = false; } else { ThemeChangeUtil.isChange = true; } ChangeTheme.this.recreate();//重新創建當前Activity實例 } }); } @Override public void onBackPressed() { super.onBackPressed(); Intent mIntent = new Intent(this, MainActivity.class); mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(mIntent); finish(); } }
主界面:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { ThemeChangeUtil.changeTheme(this); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button mSettingBtn = (Button) findViewById(R.id.btn_setting); mSettingBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { MainActivity.this.startActivity(new Intent(MainActivity.this, ChangeTheme.class)); } }); } }
以上就是Android主題切換中的白天/夜間模式的詳細過程及代碼,一開始先給大家簡單的展示了代碼,而後詳細的介紹過程及代碼,需要的朋友參考。
原因分析用戶使用android 5.0以上的系統在安裝APP時,將消息通知的權限關閉掉了。實際上用戶本意只是想關閉Notification,但是Toast的show方法中
Android之Http通信——1.初識Http協議Android之Http通信1初識Http協議 引言 正文 Http是什麼鬼 名詞解析 Htt
前言首先我們需要分析MobSF的源碼,明白一個apk的靜態分析的步驟是什麼。經過分析,如何將apk文件解壓就是進行apk行為分析的第一步,確切的說應該是第二步,第一步應該
readme:1、這個demo中沒有對多次點擊同一個聲音文件做詳細處理,偶爾會有崩潰,用的時候需要注意。2、按住錄音按鈕錄音過程中,只對豎直方向處理了一下,水平方向沒寫;