對于Android日夜間模式實現(xiàn)的探討

博文出處:對于Android日夜間模式實現(xiàn)的探討番官,歡迎大家關(guān)注我的博客原杂,謝謝!
0x0001
======

關(guān)于 Android 的日間/夜間模式切換相信大家在平時使用 APP 的過程中都遇到過瓢对,比如知乎靠胜、簡書中就有相關(guān)的模式切換。實現(xiàn)日間/夜間模式切換的方案也有許多種饮醇,趁著今天有空來講一下日間/夜間模式切換的幾種實現(xiàn)方案它抱,也可以做一個橫向的對比來看看哪種方案最好。

在本篇文章中給出了三種實現(xiàn)日間/夜間模式切換的方案:

  1. 使用 setTheme 的方法讓 Activity 重新設(shè)置主題朴艰;
  2. 設(shè)置 Android Support Library 中的 UiMode 來支持日間/夜間模式的切換观蓄;
  3. 通過資源 id 映射,回調(diào)自定義 ThemeChangeListener 接口來處理日間/夜間模式的切換祠墅。

三種方案綜合起來可能導(dǎo)致文章的篇幅過長侮穿,請耐心閱讀。

0x0002

使用 setTheme 方法

我們先來看看使用 setTheme 方法來實現(xiàn)日間/夜間模式切換的方案毁嗦。這種方案的思路很簡單亲茅,就是在用戶選擇夜間模式時,Activity 設(shè)置成夜間模式的主題狗准,之后再讓 Activity 調(diào)用 recreate() 方法重新創(chuàng)建一遍就行了克锣。

那就動手吧,在 colors.xml 中定義兩組顏色腔长,分別表示日間和夜間的主題色:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#3F51B5</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="colorAccent">#FF4081</color>

    <color name="nightColorPrimary">#3b3b3b</color>
    <color name="nightColorPrimaryDark">#383838</color>
    <color name="nightColorAccent">#a72b55</color>
</resources>

之后在 styles.xml 中定義兩組主題袭祟,也就是日間主題和夜間主題:

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:textColor">@android:color/black</item>
        <item name="mainBackground">@android:color/white</item>
    </style>

    <style name="NightAppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/nightColorPrimary</item>
        <item name="colorPrimaryDark">@color/nightColorPrimaryDark</item>
        <item name="colorAccent">@color/nightColorAccent</item>
        <item name="android:textColor">@android:color/white</item>
        <item name="mainBackground">@color/nightColorPrimaryDark</item>
    </style>

</resources>

在主題中的 mainBackground 屬性是我們自定義的屬性,用來表示背景色:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="mainBackground" format="color|reference"></attr>
</resources>

接下來就是看一下布局 activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:background="?attr/mainBackground"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.yuqirong.themedemo.MainActivity">

    <Button
        android:id="@+id/btn_theme"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="切換日/夜間模式" />

    <TextView
        android:id="@+id/tv"
        android:layout_below="@id/btn_theme"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:text="通過setTheme()的方法" />

</RelativeLayout>

<RelativeLayout>android:background 屬性中捞附,我們使用 "?attr/mainBackground" 來表示巾乳,這樣就代表著 RelativeLayout 的背景色會去引用在主題中事先定義好的 mainBackground 屬性的值。這樣就實現(xiàn)了日間/夜間模式切換的換色了鸟召。

最后就是 MainActivity 的代碼:

public class MainActivity extends AppCompatActivity {

    // 默認是日間模式
    private int theme = R.style.AppTheme;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 判斷是否有主題存儲
        if(savedInstanceState != null){
            theme = savedInstanceState.getInt("theme");
            setTheme(theme);
        }
        setContentView(R.layout.activity_main);

        Button btn_theme = (Button) findViewById(R.id.btn_theme);
        btn_theme.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                theme = (theme == R.style.AppTheme) ? R.style.NightAppTheme : R.style.AppTheme;
                MainActivity.this.recreate();
            }
        });
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("theme", theme);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        theme = savedInstanceState.getInt("theme");
    }
}

在 MainActivity 中有幾點要注意一下:

  1. 調(diào)用 recreate() 方法后 Activity 的生命周期會調(diào)用 onSaveInstanceState(Bundle outState) 來備份相關(guān)的數(shù)據(jù)想鹰,之后也會調(diào)用 onRestoreInstanceState(Bundle savedInstanceState) 來還原相關(guān)的數(shù)據(jù),因此我們把 theme 的值保存進去药版,以便 Activity 重新創(chuàng)建后使用辑舷。

  2. 我們在 onCreate(Bundle savedInstanceState) 方法中還原得到了 theme 值后,setTheme() 方法一定要在 setContentView() 方法之前調(diào)用槽片,否則的話就看不到效果了何缓。

  3. recreate() 方法是在 API 11 中添加進來的,所以在 Android 2.X 中使用會拋異常还栓。

貼完上面的代碼之后碌廓,我們來看一下該方案實現(xiàn)的效果圖:

setTheme()效果圖gif

使用 Android Support Library 中的 UiMode 方法

使用 UiMode 的方法也很簡單,我們需要把 colors.xml 定義為日間/夜間兩種。之后根據(jù)不同的模式會去選擇不同的 colors.xml 敷存。在 Activity 調(diào)用 recreate() 之后,就實現(xiàn)了切換日/夜間模式的功能痴脾。

說了這么多纪挎,直接上代碼期贫。下面是 values/colors.xml :

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#3F51B5</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="colorAccent">#FF4081</color>
    <color name="textColor">#FF000000</color>
    <color name="backgroundColor">#FFFFFF</color>
</resources>

除了 values/colors.xml 之外,我們還要創(chuàng)建一個 values-night/colors.xml 文件异袄,用來設(shè)置夜間模式的顏色通砍,其中 <color> 的 name 必須要和 values/colors.xml 中的相對應(yīng):

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#3b3b3b</color>
    <color name="colorPrimaryDark">#383838</color>
    <color name="colorAccent">#a72b55</color>
    <color name="textColor">#FFFFFF</color>
    <color name="backgroundColor">#3b3b3b</color>
</resources>

在 styles.xml 中去引用我們在 colors.xml 中定義好的顏色:

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:textColor">@color/textColor</item>
        <item name="mainBackground">@color/backgroundColor</item>
    </style>

</resources>

activity_main.xml 布局的內(nèi)容和上面 setTheme() 方法中的相差無幾,這里就不貼出來了烤蜕。之后的事情就變得很簡單了封孙,在 MyApplication 中先選擇一個默認的 Mode :

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        // 默認設(shè)置為日間模式
        AppCompatDelegate.setDefaultNightMode(
                AppCompatDelegate.MODE_NIGHT_NO);
    }

}

要注意的是,這里的 Mode 有四種類型可以選擇:

  • MODE_NIGHT_NO: 使用亮色(light)主題讽营,不使用夜間模式虎忌;
  • MODE_NIGHT_YES:使用暗色(dark)主題,使用夜間模式橱鹏;
  • MODE_NIGHT_AUTO:根據(jù)當(dāng)前時間自動切換 亮色(light)/暗色(dark)主題呐籽;
  • MODE_NIGHT_FOLLOW_SYSTEM(默認選項):設(shè)置為跟隨系統(tǒng),通常為 MODE_NIGHT_NO

當(dāng)用戶點擊按鈕切換日/夜間時蚀瘸,重新去設(shè)置相應(yīng)的 Mode :

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btn_theme = (Button) findViewById(R.id.btn_theme);
        btn_theme.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int currentNightMode = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
                getDelegate().setLocalNightMode(currentNightMode == Configuration.UI_MODE_NIGHT_NO
                        ? AppCompatDelegate.MODE_NIGHT_YES : AppCompatDelegate.MODE_NIGHT_NO);
                // 同樣需要調(diào)用recreate方法使之生效
                recreate();
            }
        });
    }

}

我們來看一下 UiMode 方案實現(xiàn)的效果圖:

UiMode的效果圖gif

就前兩種方法而言狡蝶,配置比較簡單,最后的實現(xiàn)效果也都基本上是一樣的贮勃。但是缺點就是需要調(diào)用 recreate() 使之生效贪惹。而讓 Activity 重新創(chuàng)建就必須涉及到一些狀態(tài)的保存。這就增加了一些難度寂嘉。所以奏瞬,我們一起來看看第三種解決方法。

通過資源 id 映射泉孩,回調(diào)接口

第三種方法的思路就是根據(jù)設(shè)置的主題去動態(tài)地獲取資源 id 的映射硼端,然后使用回調(diào)接口的方式讓 UI 去設(shè)置相關(guān)的屬性值。我們在這里先規(guī)定一下:夜間模式的資源在命名上都要加上后綴 “_night” 寓搬,比如日間模式的背景色命名為 color_background 珍昨,那么相對應(yīng)的夜間模式的背景資源就要命名為 color_background_night 。好了句喷,下面就是我們的 Demo 所需要用到的 colors.xml :

<?xml version="1.0" encoding="utf-8"?>
<resources>
    
    <color name="colorPrimary">#3F51B5</color>
    <color name="colorPrimary_night">#3b3b3b</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="colorPrimaryDark_night">#383838</color>
    <color name="colorAccent">#FF4081</color>
    <color name="colorAccent_night">#a72b55</color>
    <color name="textColor">#FF000000</color>
    <color name="textColor_night">#FFFFFF</color>
    <color name="backgroundColor">#FFFFFF</color>
    <color name="backgroundColor_night">#3b3b3b</color>
    
</resources>

可以看到每一項 color 都會有對應(yīng)的 “_night” 與之匹配镣典。

看到這里,肯定有人會問唾琼,為什么要設(shè)置對應(yīng)的 “_night” 兄春?到底是通過什么方式來設(shè)置日/夜間模式的呢?下面就由 ThemeManager 來為你解答:

public class ThemeManager {

    // 默認是日間模式
    private static ThemeMode mThemeMode = ThemeMode.DAY;
    // 主題模式監(jiān)聽器
    private static List<OnThemeChangeListener> mThemeChangeListenerList = new LinkedList<>();
    // 夜間資源的緩存锡溯,key : 資源類型, 值<key:資源名稱, value:int值>
    private static HashMap<String, HashMap<String, Integer>> sCachedNightResrouces = new HashMap<>();
    // 夜間模式資源的后綴赶舆,比如日件模式資源名為:R.color.activity_bg, 那么夜間模式就為 :R.color.activity_bg_night
    private static final String RESOURCE_SUFFIX = "_night";

    /**
     * 主題模式哑姚,分為日間模式和夜間模式
     */
    public enum ThemeMode {
        DAY, NIGHT
    }

    /**
     * 設(shè)置主題模式
     *
     * @param themeMode
     */
    public static void setThemeMode(ThemeMode themeMode) {
        if (mThemeMode != themeMode) {
            mThemeMode = themeMode;
            if (mThemeChangeListenerList.size() > 0) {
                for (OnThemeChangeListener listener : mThemeChangeListenerList) {
                    listener.onThemeChanged();
                }
            }
        }
    }

    /**
     * 根據(jù)傳入的日間模式的resId得到相應(yīng)主題的resId,注意:必須是日間模式的resId
     *
     * @param dayResId 日間模式的resId
     * @return 相應(yīng)主題的resId芜茵,若為日間模式叙量,則得到dayResId;反之夜間模式得到nightResId
     */
    public static int getCurrentThemeRes(Context context, int dayResId) {
        if (getThemeMode() == ThemeMode.DAY) {
            return dayResId;
        }
        // 資源名
        String entryName = context.getResources().getResourceEntryName(dayResId);
        // 資源類型
        String typeName = context.getResources().getResourceTypeName(dayResId);
        HashMap<String, Integer> cachedRes = sCachedNightResrouces.get(typeName);
        // 先從緩存中去取夕晓,如果有直接返回該id
        if (cachedRes == null) {
            cachedRes = new HashMap<>();
        }
        Integer resId = cachedRes.get(entryName + RESOURCE_SUFFIX);
        if (resId != null && resId != 0) {
            return resId;
        } else {
            //如果緩存中沒有再根據(jù)資源id去動態(tài)獲取
            try {
                // 通過資源名,資源類型悠咱,包名得到資源int值
                int nightResId = context.getResources().getIdentifier(entryName + RESOURCE_SUFFIX, typeName, context.getPackageName());
                // 放入緩存中
                cachedRes.put(entryName + RESOURCE_SUFFIX, nightResId);
                sCachedNightResrouces.put(typeName, cachedRes);
                return nightResId;
            } catch (Resources.NotFoundException e) {
                e.printStackTrace();
            }
        }
        return 0;
    }

    /**
     * 注冊ThemeChangeListener
     *
     * @param listener
     */
    public static void registerThemeChangeListener(OnThemeChangeListener listener) {
        if (!mThemeChangeListenerList.contains(listener)) {
            mThemeChangeListenerList.add(listener);
        }
    }

    /**
     * 反注冊ThemeChangeListener
     *
     * @param listener
     */
    public static void unregisterThemeChangeListener(OnThemeChangeListener listener) {
        if (mThemeChangeListenerList.contains(listener)) {
            mThemeChangeListenerList.remove(listener);
        }
    }

    /**
     * 得到主題模式
     *
     * @return
     */
    public static ThemeMode getThemeMode() {
        return mThemeMode;
    }

    /**
     * 主題模式切換監(jiān)聽器
     */
    public interface OnThemeChangeListener {
        /**
         * 主題切換時回調(diào)
         */
        void onThemeChanged();
    }
}

上面 ThemeManager 的代碼基本上都有注釋蒸辆,想要看懂并不困難。其中最核心的就是 getCurrentThemeRes 方法了析既。在這里解釋一下 getCurrentThemeRes 的邏輯躬贡。參數(shù)中的 dayResId 是日間模式的資源id,如果當(dāng)前主題是日間模式的話眼坏,就直接返回 dayResId 拂玻。反之當(dāng)前主題為夜間模式的話,先根據(jù) dayResId 得到資源名稱和資源類型宰译。比如現(xiàn)在有一個資源為 R.color.colorPrimary 檐蚜,那么資源名稱就是 colorPrimary ,資源類型就是 color 沿侈。然后根據(jù)資源類型和資源名稱去獲取緩存闯第。如果沒有緩存,那么就要動態(tài)獲取資源了缀拭。這里使用方法的是

context.getResources().getIdentifier(String name, String defType, String defPackage)
  • name 參數(shù)就是資源名稱咳短,不過要注意的是這里的資源名稱還要加上后綴 “_night” ,也就是上面在 colors.xml 中定義的名稱蛛淋;
  • defType 參數(shù)就是資源的類型了咙好。比如 color,drawable等褐荷;
  • defPackage 就是資源文件的包名勾效,也就是當(dāng)前 APP 的包名。

有了上面的這個方法叛甫,就可以通過 R.color.colorPrimary 資源找到對應(yīng)的 R.color.colorPrimary_night 資源了葵第。最后還要把找到的夜間模式資源加入到緩存中。這樣的話以后就直接去緩存中讀取合溺,而不用再次去動態(tài)查找資源 id 了卒密。

ThemeManager 中剩下的代碼應(yīng)該都是比較簡單的,相信大家都可以看得懂了棠赛。

現(xiàn)在我們來看看 MainActivity 的代碼:

public class MainActivity extends AppCompatActivity implements ThemeManager.OnThemeChangeListener {

    private TextView tv;
    private Button btn_theme;
    private RelativeLayout relativeLayout;
    private ActionBar supportActionBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ThemeManager.registerThemeChangeListener(this);
        supportActionBar = getSupportActionBar();
        btn_theme = (Button) findViewById(R.id.btn_theme);
        relativeLayout = (RelativeLayout) findViewById(R.id.relativeLayout);
        tv = (TextView) findViewById(R.id.tv);
        btn_theme.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ThemeManager.setThemeMode(ThemeManager.getThemeMode() == ThemeManager.ThemeMode.DAY
                        ? ThemeManager.ThemeMode.NIGHT : ThemeManager.ThemeMode.DAY);
            }
        });
    }

    public void initTheme() {
        tv.setTextColor(getResources().getColor(ThemeManager.getCurrentThemeRes(MainActivity.this, R.color.textColor)));
        btn_theme.setTextColor(getResources().getColor(ThemeManager.getCurrentThemeRes(MainActivity.this, R.color.textColor)));
        relativeLayout.setBackgroundColor(getResources().getColor(ThemeManager.getCurrentThemeRes(MainActivity.this, R.color.backgroundColor)));
        // 設(shè)置標題欄顏色
        if(supportActionBar != null){
            supportActionBar.setBackgroundDrawable(new ColorDrawable(getResources().getColor(ThemeManager.getCurrentThemeRes(MainActivity.this, R.color.colorPrimary))));
        }
        // 設(shè)置狀態(tài)欄顏色
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = getWindow();
            window.setStatusBarColor(getResources().getColor(ThemeManager.getCurrentThemeRes(MainActivity.this, R.color.colorPrimary)));
        }
    }

    @Override
    public void onThemeChanged() {
        initTheme();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ThemeManager.unregisterThemeChangeListener(this);
    }

}

在 MainActivity 中實現(xiàn)了 OnThemeChangeListener 接口哮奇,這樣就可以在主題改變的時候執(zhí)行回調(diào)方法膛腐。然后在 initTheme() 中去重新設(shè)置 UI 的相關(guān)顏色屬性值。還有別忘了要在 onDestroy() 中移除 ThemeChangeListener 鼎俘。

最后就來看看第三種方法的效果吧:

動態(tài)獲取資源id的效果圖gif

也許有人會說和前兩種方法的效果沒什么差異啊哲身,但是仔細看就會發(fā)現(xiàn)前面兩種方法在切換模式的瞬間會有短暫黑屏現(xiàn)象存在,而第三種方法沒有贸伐。這是因為前兩種方法都要調(diào)用 recreate() 勘天。而第三種方法不需要 Activity 重新創(chuàng)建,使用回調(diào)的方法來實現(xiàn)捉邢。

0x0003

到了這里脯丝,按照套路應(yīng)該是要總結(jié)的時候了。那么就根據(jù)上面給的三種方法來一個簡單的對比吧:

  1. setTheme 方法:可以配置多套主題伏伐,比較容易上手宠进。除了日/夜間模式之外,還可以有其他五顏六色的主題藐翎。但是需要調(diào)用 recreate() 材蹬,切換瞬間會有黑屏閃現(xiàn)的現(xiàn)象;

  2. UiMode 方法:優(yōu)點就是 Android Support Library 中已經(jīng)支持吝镣,簡單規(guī)范堤器。但是也需要調(diào)用 recreate() ,存在黑屏閃現(xiàn)的現(xiàn)象末贾;

  3. 動態(tài)獲取資源 id 吼旧,回調(diào)接口:該方法使用起來比前兩個方法復(fù)雜,另外在回調(diào)的方法中需要設(shè)置每一項 UI 相關(guān)的屬性值未舟。但是不需要調(diào)用 recreate() 圈暗,沒有黑屏閃現(xiàn)的現(xiàn)象。

三種方法整體的對比就如上所示了裕膀。當(dāng)然除了上面的三種方法實現(xiàn)日/夜間模式切換之外员串,還有比如動態(tài)換膚等也都可以實現(xiàn)。方法有很多種昼扛,重要的是要根據(jù)自身情況選擇合適的方法去實現(xiàn)寸齐。在下面我會給出其他幾種實現(xiàn)日/夜間模式切換方法的鏈接,可以參考一下抄谐。

好了渺鹦,到了說再見的時候了。

Goodbye !

setTheme方法的Demo下載

UiMode方法的Demo下載

動態(tài)獲取資源id方法的Demo下載

0x0004

android 實現(xiàn)【夜晚模式】的另外一種思路

知乎和簡書的夜間模式實現(xiàn)套路

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蛹含,一起剝皮案震驚了整個濱河市毅厚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌浦箱,老刑警劉巖吸耿,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件祠锣,死亡現(xiàn)場離奇詭異,居然都是意外死亡咽安,警方通過查閱死者的電腦和手機伴网,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妆棒,“玉大人澡腾,你說我怎么就攤上這事「馍海” “怎么了动分?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長放接。 經(jīng)常有香客問我刺啦,道長留特,這世上最難降的妖魔是什么纠脾? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮蜕青,結(jié)果婚禮上苟蹈,老公的妹妹穿的比我還像新娘。我一直安慰自己右核,他們只是感情好慧脱,可當(dāng)我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著贺喝,像睡著了一般菱鸥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上躏鱼,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天氮采,我揣著相機與錄音,去河邊找鬼染苛。 笑死鹊漠,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的茶行。 我是一名探鬼主播躯概,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼畔师!你這毒婦竟也來了娶靡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤看锉,失蹤者是張志新(化名)和其女友劉穎固蛾,沒想到半個月后结执,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡艾凯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年献幔,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片趾诗。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡蜡感,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出恃泪,到底是詐尸還是另有隱情郑兴,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布贝乎,位于F島的核電站情连,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏览效。R本人自食惡果不足惜却舀,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望锤灿。 院中可真熱鬧挽拔,春花似錦、人聲如沸但校。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽状囱。三九已至术裸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間亭枷,已是汗流浹背袭艺。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留奶栖,地道東北人匹表。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像宣鄙,于是被迫代替她去往敵國和親袍镀。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內(nèi)容