13

昼/夜のテーマを実装する必要があるアプリがあります。残念ながら、スタイルを使用してテーマを作成する簡単な方法はありません。レイアウトの背景、ボタン セレクター、テキストの色、テキストのサイズ、画像、アイコン、アニメーションを更新できるようにする必要があります。

私が見たところ、2つのオプションがあります。

  1. home_day.xml夜と昼で異なるxmlレイアウトファイルを持っているので、 /のようなものhome_night.xmlです。アプリには約 30 の画面があるため、最終的には 60 の xml レイアウトになります。アクティビティ/フラグメントonCreateで、現在の時間に基づいてできsetContentViewました。これにより、いくつかの xml ファイルが追加されますが、アクティビティにコードを追加する必要がなくなります

  2. テーマにしたいアイテムごとに昼/夜とアクティビティのonCreatefindviewByIdのレイアウトを1つだけ持ち、現在の昼/夜に基づいて属性を更新します。これにより、多くの余分なコード、findviews、および多くのビューの属性の適用が生成される可能性があります。

私は2.を目指していますが、あなたからの提案をお待ちしています。それで、あなたは何を選びますか、そしてなぜですか?

4

6 に答える 6

19

-nightナイト モードのリソース セット修飾子として使用し、ナイト固有のリソースをそこに配置します。

Android にはすでにナイト モードの概念があり、時刻とセンサーに基づいてナイト モードとデイタイム モードを切り替えます。したがって、あなたはそれを使用することを検討するかもしれません。

たとえば、モードに基づいて異なるテーマを作成するには、 と を作成res/values/styles.xmlres/values-night/styles.xmlます。各ファイルに同じ名前のテーマ (例: AppTheme) を用意しますが、昼モードと夜モードの違いに応じてテーマを調整します。テーマを名前で (マニフェストなどで) 参照すると、Android は自動的に適切なリソースを読み込み、アクティビティの実行中にモードが変更された場合、Android はアクティビティを自動的に破棄して再作成します。

現在、夜をテーマにした UI を使用するかどうかをユーザーが手動で制御したい場合は、-night役に立ちません。

于 2013-08-01T21:24:30.730 に答える
16

完全なステップバイステップの例については、このチュートリアルを確認してください:ここをクリック

Appcompat v23.2 サポート ライブラリを使用して自動切り替え DayNight テーマを追加

build.gradleファイルに次の行を追加します

compile 'com.android.support:appcompat-v7:23.2.0'

以下のようにテーマスタイルを作成styles.xmlします

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.DayNight.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:textColorPrimary">@color/textColorPrimary</item>
        <item name="android:textColorSecondary">@color/textColorSecondary</item>
    </style>
</resources>

onCreate()アプリ全体のテーマを設定するために、次の行コード メソッドを追加します。

デフォルトの自動切り替えナイトモードを設定するには

AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO);

デフォルトのナイトモードを設定するには

AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);

デフォルトのデイモードを設定するには

AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);

ここに画像の説明を入力

于 2016-03-11T08:36:54.687 に答える
5

ここに私の解決策があります:

  • 自動の昼夜機能が欲しかったのですが、アンドロイドで面倒なカーモードを有効にする必要はありませんでした。

-> NOAA の Web ページから、特定の位置と日付を指定して、地平線上の太陽の高さを計算するアルゴリズムを見つけることができます。

--> これらのアルゴリズムを使用して、緯度と経度の 2 つの double 値とカレンダーを指定して、地平線上の太陽の高さを計算するメソッドを作成しました。

public class SolarCalculations {

    /**
     * Calculate height of the sun above horizon for a given position and date
     * @param lat Positive to N
     * @param lon Positive to E
     * @param cal Calendar containing current time, date, timezone, daylight time savings
     * @return height of the sun in degrees, positive if above the horizon
     */
    public static double CalculateSunHeight(double lat, double lon, Calendar cal){

        double adjustedTimeZone = cal.getTimeZone().getRawOffset()/3600000 + cal.getTimeZone().getDSTSavings()/3600000;

        double timeOfDay = (cal.get(Calendar.HOUR_OF_DAY) * 3600 + cal.get(Calendar.MINUTE) * 60 + cal.get(Calendar.SECOND))/(double)86400;

        double julianDay = dateToJulian(cal.getTime()) - adjustedTimeZone/24;

        double julianCentury = (julianDay-2451545)/36525;

        double geomMeanLongSun = (280.46646 + julianCentury * (36000.76983 + julianCentury * 0.0003032)) % 360;

        double geomMeanAnomSun = 357.52911+julianCentury*(35999.05029 - 0.0001537*julianCentury);

        double eccentEarthOrbit = 0.016708634-julianCentury*(0.000042037+0.0000001267*julianCentury);

        double sunEqOfCtr = Math.sin(Math.toRadians(geomMeanAnomSun))*(1.914602-julianCentury*(0.004817+0.000014*julianCentury))+Math.sin(Math.toRadians(2*geomMeanAnomSun))*(0.019993-0.000101*julianCentury)+Math.sin(Math.toRadians(3*geomMeanAnomSun))*0.000289;

        double sunTrueLong = geomMeanLongSun + sunEqOfCtr;

        double sunAppLong = sunTrueLong-0.00569-0.00478*Math.sin(Math.toRadians(125.04-1934.136*julianCentury));

        double meanObliqEcliptic = 23+(26+((21.448-julianCentury*(46.815+julianCentury*(0.00059-julianCentury*0.001813))))/60)/60;

        double obliqueCorr = meanObliqEcliptic+0.00256*Math.cos(Math.toRadians(125.04-1934.136*julianCentury));

        double sunDeclin = Math.toDegrees(Math.asin(Math.sin(Math.toRadians(obliqueCorr))*Math.sin(Math.toRadians(sunAppLong))));

        double varY = Math.tan(Math.toRadians(obliqueCorr/2))*Math.tan(Math.toRadians(obliqueCorr/2));

        double eqOfTime = 4*Math.toDegrees(varY*Math.sin(2*Math.toRadians(geomMeanLongSun))-2*eccentEarthOrbit*Math.sin(Math.toRadians(geomMeanAnomSun))+4*eccentEarthOrbit*varY*Math.sin(Math.toRadians(geomMeanAnomSun))*Math.cos(2*Math.toRadians(geomMeanLongSun))-0.5*varY*varY*Math.sin(4*Math.toRadians(geomMeanLongSun))-1.25*eccentEarthOrbit*eccentEarthOrbit*Math.sin(2*Math.toRadians(geomMeanAnomSun)));

        double trueSolarTime = (timeOfDay*1440+eqOfTime+4*lon-60*adjustedTimeZone) % 1440;

        double hourAngle;
        if(trueSolarTime/4<0)
            hourAngle = trueSolarTime/4+180;
        else
            hourAngle = trueSolarTime/4-180;

        double solarZenithAngle = Math.toDegrees(Math.acos(Math.sin(Math.toRadians(lat))*Math.sin(Math.toRadians(sunDeclin))+Math.cos(Math.toRadians(lat))*Math.cos(Math.toRadians(sunDeclin))*Math.cos(Math.toRadians(hourAngle))));

        double solarElevation = 90 - solarZenithAngle;

        double athmosphericRefraction;
        if(solarElevation>85)
            athmosphericRefraction = 0;
        else if(solarElevation>5)
            athmosphericRefraction = 58.1/Math.tan(Math.toRadians(solarElevation))-0.07/Math.pow(Math.tan(Math.toRadians(solarElevation)),3)+0.000086/Math.pow(Math.tan(Math.toRadians(solarElevation)),5);
        else if(solarElevation>-0.575)
            athmosphericRefraction = 1735+solarElevation*(-518.2+solarElevation*(103.4+solarElevation*(-12.79+solarElevation*0.711)));
        else
            athmosphericRefraction = -20.772/Math.tan(Math.toRadians(solarElevation));
        athmosphericRefraction /= 3600;

        double solarElevationCorrected = solarElevation + athmosphericRefraction;

        return solarElevationCorrected;

    }


    /**
     * Return Julian day from date
     * @param date
     * @return
     */
    public static double dateToJulian(Date date) {

        GregorianCalendar calendar = new GregorianCalendar();
        calendar.setTime(date);

        int a = (14-(calendar.get(Calendar.MONTH)+1))/12;
        int y = calendar.get(Calendar.YEAR) + 4800 - a;

        int m =  (calendar.get(Calendar.MONTH)+1) + 12*a;
        m -= 3;

        double jdn = calendar.get(Calendar.DAY_OF_MONTH) + (153.0*m + 2.0)/5.0 + 365.0*y + y/4.0 - y/100.0 + y/400.0 - 32045.0 + calendar.get(Calendar.HOUR_OF_DAY) / 24 + calendar.get(Calendar.MINUTE)/1440 + calendar.get(Calendar.SECOND)/86400;

        return jdn;
    } 
}

次に MainActivity には、指定された位置での太陽の高さを 5 分ごとにチェックするメソッドがあります。

 if(displayMode.equals("auto")){
        double sunHeight = SolarCalculations.CalculateSunHeight(lat, lon, cal);
        if(sunHeight > 0 && mThemeId != R.style.AppTheme_Daylight)
        {//daylight mode
            mThemeId = R.style.AppTheme_Daylight;   
            this.recreate();
        }
        else if (sunHeight < 0 && sunHeight >= -6 && mThemeId != R.style.AppTheme_Dusk)
        {//civil dusk
            mThemeId = R.style.AppTheme_Dusk;
            this.recreate();
        }
        else if(sunHeight < -6 && mThemeId != R.style.AppTheme_Night)
        {//night mode
            mThemeId = R.style.AppTheme_Night;
            this.recreate();
        }
    }

このメソッドは、使用する現在のスタイルを設定します。私はそれらのうちの 3 つを持っています。昼と夜に 2 つ、太陽光が大気中に屈折し始める夕暮れに 1 つ

<!-- Application theme. -->
<style name="AppTheme.Daylight" parent="AppBaseTheme">
    <item name="android:background">@color/white</item>
    <item name="android:panelBackground">@color/gray</item>
    <item name="android:textColor">@color/black</item>
</style>

<style name="AppTheme.Dusk" parent="AppBaseTheme">
    <item name="android:background">@color/black</item>
    <item name="android:panelBackground">@color/gray</item>
    <item name="android:textColor">@color/salmon</item>
</style>

<style name="AppTheme.Night" parent="AppBaseTheme">
    <item name="android:background">@color/black</item>
    <item name="android:panelBackground">@color/gray</item>
    <item name="android:textColor">@color/red</item>
</style>

これはかなりうまく機能しており、夏時間の修正を考慮に入れています。

ソース:

NOAA日の出日の入り

ユリウス日

于 2014-04-17T02:57:18.950 に答える