Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android 夜間模式的實現

android 夜間模式的實現

編輯:關於Android編程

注:急速開發的人,可以直接看第三種實現方式

1:修改theme,重啟activity(Google自家在內的很多應用都是采用此種方式實現夜間模式的)

優點:正兒八經的夜間模式,配色看著舒服

缺點:規模較大的應用,需要隨theme變化的屬性會很多,都需要逐一定義,有點麻煩,另外一個缺點是要使得新theme生效,一般需要restartActivity來切換UI,會導致切換主題時界面閃爍

核心思路:自定義一個顏色屬性名 A,A在日間和夜間模式下都有具體的顏色代碼,頁面布局文件只管引用A,至於是日間還是夜間,由後台主題決定。

\ \

附上一二中方法的圖

\(原圖)\(第一種實現)\(第二種實現)

好,下面來講講具體的實現步驟,本環節使用的開發環境是Eclipse demo地址http://www.oschina.net/code/snippet_2702417_55892

1 首先

attrs.xml(聲明屬性的類型,布局xml中用) reference可以使用系統的資源ID,比如R.color.gray; color可以直接使用#ffffff顏色代碼
 

 <attr name="colorValue" format="color" />  
    <attr name="floatValue" format="float" />  
    <attr name="integerValue" format="integer" />  
    <attr name="booleanValue" format="boolean" />  
    <attr name="dimensionValue" format="dimension" />  
    <attr name="stringValue" format="string" />  
    <attr name="referenceValue" format="color|reference" />  
    <attr name="imageValue" format="reference"/>  
  
    <attr name="curVisibility"> 
        <!-- 相當於View的Visiblity --> 
    <enum name="show" value="0" />  
    <!-- Not displayed, but taken into account during layout (space is left for it).相當於View的unVisiblity -->  
    <enum name="inshow" value="1" />  
    <!-- Completely hidden, as if the view had not been added.相當於View的GONE -->  
    <enum name="hide" value="2" />  
    </attr> 

colors.xml(調色板,集中管理顏色hex)遵循優秀格式規范,即調色板模式,避免使用btn1,btn2,fontTitle,fontText之類的顏色名。
 

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <color name="title">#101115</color>
   <color name="night_title">#FFFFFF</color> 
</resources>

string.xml

<string name="app_name">dayandNight</string>  
   <string name="hello_world">Hello world!</string>  
   <string name="action_settings">白模式</string>  
   <string name="night_action_settings">夜模式</string>  

styles.xml(日間、夜間主題)
 

<resources>
      <style name="AppBaseTheme" parent="android:Theme.Light">
        <!--
            Theme customizations available in newer API levels can go in
            res/values-vXX/styles.xml, while customizations related to
            backward-compatibility can go here.


        -->
    </style>

    <!-- Application theme. -->
    <style name="AppTheme" parent="AppBaseTheme">
        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
    </style>
    

    <style name="DayTheme" parent="AppTheme">
        <item name="colorValue">@color/title</item>
        <item name="floatValue">0.35</item>
        <item name="integerValue">33</item>
        <item name="booleanValue">true</item>
        <item name="dimensionValue">16dp</item>
        <!-- 如果string類型不是填的引用而是直接放一個字符串,在布局文件中使用正常,但代碼裡獲取的就有問題 -->
        <item name="stringValue">@string/action_settings</item>
        <item name="referenceValue">@drawable/bg</item>
        <item name="imageValue">@drawable/day</item>
        <item name="curVisibility">show</item>
    </style>

    <style name="NightTheme" parent="AppTheme">
        <item name="colorValue">@color/night_title</item>
        <item name="floatValue">1.44</item>
        <item name="integerValue">55</item>
        <item name="booleanValue">false</item>
        <item name="dimensionValue">18sp</item>
        <item name="stringValue">@string/night_action_settings</item>
        <item name="referenceValue">@drawable/night_bg</item>
        <item name="imageValue">@drawable/night</item>
        <item name="curVisibility">hide</item>
    </style>
</resources>

2activity的使用

 

protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		if(MyApp.isLightMode()){  
            this.setTheme(R.style.NightTheme);  
        }else{  
            this.setTheme(R.style.DayTheme);  
        }  
		setContentView(R.layout.activity_one);
	}
	
	public void onClick(View view){
		MyApp.setIslightMode(!MyApp.isLightMode());
		recreate();
	}

xml的布局:
 

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:background="?attr/referenceValue"  
    android:orientation="vertical"  
    android:gravity="center" >  
  
    <TextView  
        android:id="@+id/setting_Color"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="TextView"  
        android:textColor="?attr/colorValue" />  
  
    <CheckBox  
        android:id="@+id/setting_show_answer_switch"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:checked="?attr/booleanValue" />  
  
    <TextView  
        android:id="@+id/setting_Title"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="pszwzy"  
        android:textColor="?attr/colorValue"  
        android:textSize="?attr/dimensionValue" />  
  
    <TextView  
        android:id="@+id/setting_Text"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="?attr/stringValue" />  
  
    <ImageView  
        android:id="@+id/setting_Image"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:src="?attr/imageValue" />  
  
    <View  
        android:id="@+id/setting_line"  
        android:layout_width="match_parent"  
        android:layout_height="1dp"  
        android:visibility="?attr/curVisibility" />  
    <Button   
        android:onClick="onClick"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:text="模式切換"  
        android:textColor="?attr/colorValue"          
        />  
  
</LinearLayout>  
注:遇到放回activity閃屏的問題可以

 

(1)在BaseActivity中創建下面的方法

public static void updateTheme(Activity activity,isNight)
{
  MyApp.setNightMode(isNight);
  activity.recreate();
}


 

2:使用一個帶黑色帶透明度的View,蓋在現有的activity上,效果類似你帶上墨鏡,看著太陽不刺眼。

//第二中方式,只是提供一種思路,邏輯沒有去實習  
    public void onClickT(View view){  
        LayoutParams  mNightViewParam = new LayoutParams(  
                    LayoutParams.TYPE_APPLICATION,  
                    LayoutParams.FLAG_NOT_TOUCHABLE | LayoutParams.FLAG_NOT_FOCUSABLE,  
                    PixelFormat.TRANSPARENT);  
  
        WindowManager   mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);  
        View   mNightView = new View(this);  
        mWindowManager.addView(mNightView, mNightViewParam);  
        mNightView.setBackgroundResource(R.color.night_mask);  
}  
先看下BaseActivity
public abstract class BaseActivity extends Activity {  
protected int skin;  
public Context mContext;  
SharedPreferences sp;  
  
  
@Override  
protected void onCreate(Bundle savedInstanceState) {  
<span style="white-space:pre">    </span>setThemeMode(getSkinTypeValue());  
<span style="white-space:pre">    </span>super.onCreate(savedInstanceState);  
<span style="white-space:pre">    </span>init();  
<span style="white-space:pre">    </span>}  
<span style="white-space:pre">    </span>public abstract void init();  
<span style="white-space:pre">    </span>protected void setThemeMode(SkinType skinType) {  
<span style="white-space:pre">    </span>  switch (skinType) {  
<span style="white-space:pre">    </span>  case Light:  
<span style="white-space:pre">        </span>setTheme(R.style.AppTheme_Light);  

<span style="white-space:pre">    </span>  break;  
<span style="white-space:pre">    </span> case Night:  
<span style="white-space:pre">        </span>setTheme(R.style.AppTheme_Night);  
<span style="white-space:pre">    </span> break;  
<span style="white-space:pre">    </span> default:  
<span style="white-space:pre">        </span>setTheme(R.style.AppTheme_Light);  
<span style="white-space:pre">    </span> break;  
<span style="white-space:pre">    </span>}  
}  
//獲取用戶選取的模式  
protected SkinType getSkinTypeValue() {  
<span style="white-space:pre">    </span>if (sp == null) {  
<span style="white-space:pre">    </span>sp = getSharedPreferences("AppSkinType", Context.MODE_PRIVATE);  
<span style="white-space:pre">    </span>}  
<span style="white-space:pre">    </span>int i = sp.getInt("AppSkinTypeValue", 0);  
<span style="white-space:pre">    </span>switch (i) {  
<span style="white-space:pre">    </span> case 0:  
<span style="white-space:pre">        </span>return SkinType.Light;  
      case 1:  
<span style="white-space:pre">        </span>return SkinType.Night;  
<span style="white-space:pre">    </span> default:  
<span style="white-space:pre">    </span> break;  
<span style="white-space:pre">    </span>}  
<span style="white-space:pre">    </span>return SkinType.Light;  
}  
//保存用戶是選取的模式  
public void saveSkinValue(int skin) {  
<span style="white-space:pre">    </span>if (sp == null) {  
<span style="white-space:pre">    </span>sp = getSharedPreferences("AppSkinType", Context.MODE_PRIVATE);  
<span style="white-space:pre">    </span>}  
<span style="white-space:pre">    </span>Editor editor = sp.edit();  
<span style="white-space:pre">    </span>editor.putInt("AppSkinTypeValue", skin);  
<span style="white-space:pre">    </span>editor.commit();  
  
}  
在看下第一個activity的使用的
public class MainActivity extends BaseActivity {  
    private CheckBox cbSetting;  
    private Button btnForward;  
    private TextView tv_title;  
    private View llNight;  
      
      
    @Override  
    public void init() {  
        setContentView(R.layout.activity_main);  
        llNight = findViewById(R.id.ll_night);  
        tv_title = (TextView) findViewById(R.id.tv_title);  
        btnForward = (Button) findViewById(R.id.forward);  
        cbSetting = (CheckBox) findViewById(R.id.cb_setting);  
        cbSetting.setOnCheckedChangeListener(new OnCheckedChangeListener() {  
            @Override  
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {  
                if (isChecked) {  
                    // 夜間模式  
                    saveSkinValue(1);  
                    setTheme(R.style.AppTheme_Night);//防止getTheme()取出來的值是創建時候得值  
                    initView();  
                } else {  
                    // 白天模式  
                    saveSkinValue(0);  
                    setTheme(R.style.AppTheme_Light);//防止getTheme()取出來的值是創建時候得值  
                    initView();   
                }  
            }  
        });  
          
        btnForward.setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                Intent intent = new Intent(MainActivity.this,SecondActivity.class);  
                startActivity(intent);  
            }  
        });  
    }  
    //改變模式後手動修改UI,不然出現閃屏  
    private void initView(){  
        <span style="color:#ff6666;">TypedValue typedValue = new TypedValue();  
        Theme theme = getTheme();  
        theme.resolveAttribute(R.attr.gray_3_double, typedValue, true);     
        btnForward.setTextColor(getResources().getColor(typedValue.resourceId));  
        tv_title.setTextColor(getResources().getColor(typedValue.resourceId));  
        theme.resolveAttribute(R.attr.source_bg, typedValue, true);     
        llNight.setBackgroundDrawable(getResources().getDrawable(typedValue.resourceId));</span>    
    }     
}  
大體就是這樣實現
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved