IT

Android Lollipop에서 _really_ 프로그래밍 방식으로 기본 및 악센트 색상을 변경하는 방법은 무엇입니까?

lottoking 2020. 6. 13. 09:38
반응형

Android Lollipop에서 _really_ 프로그래밍 방식으로 기본 및 악센트 색상을 변경하는 방법은 무엇입니까?


우선, 이 질문 은 매우 비슷한 질문을합니다. 그러나 내 질문에는 미묘한 차이가 있습니다.

내가 알고 싶은 것은 프로그래밍 방식 colorPrimary으로 테마 속성을 임의의 색상으로 변경할 수 있는지 여부 입니다.

예를 들어, 우리는 :

<style name="AppTheme" parent="android:Theme.Material.Light">
    <item name="android:colorPrimary">#ff0000</item>
    <item name="android:colorAccent">#ff0000</item>
</style>

런타임시 사용자는 #ccffff기본 색상 으로 사용하기 결정 합니다. 물론 가능한 모든 색상에 대한 테마를 만들 수있는 방법은 없습니다.

공개 SDK를 사용하여 작동하는 한 Android의 개인 내부 정보에 의존하는 것처럼 해킹이 필요한 작업은 신경 쓰지 않습니다.

내 목표는 결국하는 것입니다 ActionBar A는 같은 모든 위젯 CheckBox이 원색을 사용합니다.


테마는 변경할 수 없습니다.


연락처 앱에 대한 의견과 각 연락처에 테마를 사용하는 방법을 읽었습니다.

아마도 연락처 앱에는 몇 가지 사전 정의 된 테마가 있습니다 ( http://www.google.com/design/spec/style/color.html ).

onCreate 메소드에서 setContentView 메소드 앞에 테마를 적용 할 수 있습니다.

그런 다음 연락처 앱은 각 사용자에게 테마를 무작위로 적용 할 수 있습니다.

이 방법은 다음과 같습니다

setTheme(R.style.MyRandomTheme);

그러나이 방법에는 문제가 있습니다. 예를 들어 툴바 색상, 스크롤 효과 색상, 잔물결 색상 등을 변경할 수 있지만 상태 표시 줄 색상과 탐색 막대 색상을 변경할 수는 없습니다 (변경하려는 경우).

그런 다음이 문제를 해결하기 위해 이전과 다음 방법을 사용할 수 있습니다.

if (Build.VERSION.SDK_INT >= 21) {
        getWindow().setNavigationBarColor(getResources().getColor(R.color.md_red_500));
        getWindow().setStatusBarColor(getResources().getColor(R.color.md_red_700));
    }

이 두 가지 방법은 탐색 및 상태 표시 줄 색상을 변경합니다. 탐색 막대를 반투명으로 설정하면 색상을 변경할 수 없습니다.

마지막 코드 여야합니다.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setTheme(R.style.MyRandomTheme);
    if (Build.VERSION.SDK_INT >= 21) {
        getWindow().setNavigationBarColor(getResources().getColor(R.color.myrandomcolor1));
        getWindow().setStatusBarColor(getResources().getColor(R.color.myrandomcolor2));
    }
    setContentView(R.layout.activity_main);

}

스위치를 사용하고 임의의 숫자를 생성하여 임의의 테마를 사용하거나 연락처 앱에서와 같이 각 연락처에는 미리 정의 된 번호가있을 수 있습니다.

테마 샘플 :

<style name="MyRandomTheme" parent="Theme.AppCompat.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/myrandomcolor1</item>
    <item name="colorPrimaryDark">@color/myrandomcolor2</item>
    <item name="android:navigationBarColor">@color/myrandomcolor1</item>
</style>

내 영어가 유감입니다.


Theme.applyStyle사용 하여 다른 스타일을 적용하여 런타임에 테마를 수정할 수 있습니다 .

이 스타일 정의가 있다고 가정 해 봅시다.

<style name="DefaultTheme" parent="Theme.AppCompat.Light">
    <item name="colorPrimary">@color/md_lime_500</item>
    <item name="colorPrimaryDark">@color/md_lime_700</item>
    <item name="colorAccent">@color/md_amber_A400</item>
</style>

<style name="OverlayPrimaryColorRed">
    <item name="colorPrimary">@color/md_red_500</item>
    <item name="colorPrimaryDark">@color/md_red_700</item>
</style>

<style name="OverlayPrimaryColorGreen">
    <item name="colorPrimary">@color/md_green_500</item>
    <item name="colorPrimaryDark">@color/md_green_700</item>
</style>

<style name="OverlayPrimaryColorBlue">
    <item name="colorPrimary">@color/md_blue_500</item>
    <item name="colorPrimaryDark">@color/md_blue_700</item>
</style>

이제 런타임에 테마를 다음과 같이 패치 할 수 있습니다.

getTheme().applyStyle(R.style.OverlayPrimaryColorGreen, true);

applyStyle레이아웃이 팽창하기 전에 메소드 를 호출해야합니다! 따라서보기를 수동으로로드하지 않으면 setContentView활동을 호출하기 전에 테마에 스타일을 적용 해야합니다.

물론 이것은 임의의 색상, 즉 1600 만 (256 3 ) 색상 중 하나를 지정하는 데 사용할 수 없습니다 . 그러나 스타일 정의와 Java 코드를 생성하는 작은 프로그램을 작성하면 512 (8 3 ) 중 하나와 같은 것이 가능해야합니다.

흥미로운 점은 테마의 여러 ​​측면에 다른 스타일 오버레이를 사용할 수 있다는 것입니다. colorAccent예를 들어 몇 가지 오버레이 정의를 추가하십시오 . 이제 기본 색상과 악센트 색상에 대한 다양한 값을 거의 임의로 조합 할 수 있습니다 .

오버레이 테마 정의가 실수로 상위 스타일 정의에서 여러 스타일 정의를 상속하지 않도록해야합니다. 예를 들어, 스타일이라는 AppTheme.OverlayRed암시 적 스타일은 정의 된 모든 스타일을 상속 AppTheme하며 마스터 테마를 패치 할 때 이러한 모든 정의도 적용됩니다. 따라서 오버레이 테마 이름에서 점을 피하거나 비슷한 것을 사용 하고 빈 스타일로 Overlay.Red정의하십시오 Overlay.


나는 모든 색 테마를 만들기 위해 몇 가지 해결책을 만들었습니다. 어쩌면 이것은 누군가에게 유용 할 수 있습니다. API 9+

1. 먼저 " res / values-v9 / "를 생성 하고이 파일을 넣으십시오 : styles.xml 및 일반 "res / values"폴더가 스타일과 함께 사용됩니다.

2. 이 코드를 res / values ​​/ styles.xml에 넣으십시오.

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light">
        <item name="colorPrimary">#000</item>
        <item name="colorPrimaryDark">#000</item>
        <item name="colorAccent">#000</item>
        <item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
    </style>

    <style name="AppThemeDarkActionBar" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">#000</item>
        <item name="colorPrimaryDark">#000</item>
        <item name="colorAccent">#000</item>
        <item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
    </style>

    <style name="WindowAnimationTransition">
        <item name="android:windowEnterAnimation">@android:anim/fade_in</item>
        <item name="android:windowExitAnimation">@android:anim/fade_out</item>
    </style>
</resources>

3. AndroidManifest에 :

<application android:theme="@style/AppThemeDarkActionBar">

4. 이름이 "ThemeColors.java"인 새 클래스를 작성하십시오.

public class ThemeColors {

    private static final String NAME = "ThemeColors", KEY = "color";

    @ColorInt
    public int color;

    public ThemeColors(Context context) {
        SharedPreferences sharedPreferences = context.getSharedPreferences(NAME, Context.MODE_PRIVATE);
        String stringColor = sharedPreferences.getString(KEY, "004bff");
        color = Color.parseColor("#" + stringColor);

        if (isLightActionBar()) context.setTheme(R.style.AppTheme);
        context.setTheme(context.getResources().getIdentifier("T_" + stringColor, "style", context.getPackageName()));
    }

    public static void setNewThemeColor(Activity activity, int red, int green, int blue) {
        int colorStep = 15;
        red = Math.round(red / colorStep) * colorStep;
        green = Math.round(green / colorStep) * colorStep;
        blue = Math.round(blue / colorStep) * colorStep;

        String stringColor = Integer.toHexString(Color.rgb(red, green, blue)).substring(2);
        SharedPreferences.Editor editor = activity.getSharedPreferences(NAME, Context.MODE_PRIVATE).edit();
        editor.putString(KEY, stringColor);
        editor.apply();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) activity.recreate();
        else {
            Intent i = activity.getPackageManager().getLaunchIntentForPackage(activity.getPackageName());
            i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            activity.startActivity(i);
        }
    }

    private boolean isLightActionBar() {// Checking if title text color will be black
        int rgb = (Color.red(color) + Color.green(color) + Color.blue(color)) / 3;
        return rgb > 210;
    }
}

5. setContentView (R.layout.activity_main)을 호출하기 전에 다음을 추가하십시오.

new ThemeColors(this);

색상을 변경하려면 RGB로 무작위를 대체하십시오.

    findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int red= new Random().nextInt(255);
            int green= new Random().nextInt(255);
            int blue= new Random().nextInt(255);
            ThemeColors.setNewThemeColor(MainActivity.this, red, green, blue);
        }
    });

여기에 이미지 설명을 입력하십시오


Dahnark의 코드를 사용했지만 ToolBar 배경도 변경해야합니다.

if (dark_ui) {
    this.setTheme(R.style.Theme_Dark);

    if (Build.VERSION.SDK_INT >= 21) {
        getWindow().setNavigationBarColor(getResources().getColor(R.color.Theme_Dark_primary));
        getWindow().setStatusBarColor(getResources().getColor(R.color.Theme_Dark_primary_dark));
    }
} else {
    this.setTheme(R.style.Theme_Light);
}

setContentView(R.layout.activity_main);

toolbar = (Toolbar) findViewById(R.id.app_bar);

if(dark_ui) {
    toolbar.setBackgroundColor(getResources().getColor(R.color.Theme_Dark_primary));
}

colorPrimary의 색상을 변경할 수는 없지만 다른 colorPrimary 색상으로 새 스타일을 추가하여 응용 프로그램의 테마를 변경할 수 있습니다

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
</style>

<style name="AppTheme.NewTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/colorOne</item>
    <item name="colorPrimaryDark">@color/colorOneDark</item>
</style>

활동 세트 테마 내부

 setTheme(R.style.AppTheme_NewTheme);
 setContentView(R.layout.activity_main);

당신이 할 수있는 활동에서 :

getWindow().setStatusBarColor(i color);

툴바 사용

사용자 정의 도구 모음 클래스를 작성하여 사용자 정의 도구 모음 항목 색상을 동적으로 설정할 수 있습니다 .

package view;

import android.app.Activity;
import android.content.Context;
import android.graphics.ColorFilter;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.support.v7.internal.view.menu.ActionMenuItemView;
import android.support.v7.widget.ActionMenuView;
import android.support.v7.widget.Toolbar;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AutoCompleteTextView;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;

public class CustomToolbar extends Toolbar{

    public CustomToolbar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // TODO Auto-generated constructor stub
    }

    public CustomToolbar(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }

    public CustomToolbar(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        ctxt = context;
    }

    int itemColor;
    Context ctxt;

    @Override 
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        Log.d("LL", "onLayout");
        super.onLayout(changed, l, t, r, b);
        colorizeToolbar(this, itemColor, (Activity) ctxt);
    } 

    public void setItemColor(int color){
        itemColor = color;
        colorizeToolbar(this, itemColor, (Activity) ctxt);
    }



    /**
     * Use this method to colorize toolbar icons to the desired target color
     * @param toolbarView toolbar view being colored
     * @param toolbarIconsColor the target color of toolbar icons
     * @param activity reference to activity needed to register observers
     */
    public static void colorizeToolbar(Toolbar toolbarView, int toolbarIconsColor, Activity activity) {
        final PorterDuffColorFilter colorFilter
                = new PorterDuffColorFilter(toolbarIconsColor, PorterDuff.Mode.SRC_IN);

        for(int i = 0; i < toolbarView.getChildCount(); i++) {
            final View v = toolbarView.getChildAt(i);

            doColorizing(v, colorFilter, toolbarIconsColor);
        }

      //Step 3: Changing the color of title and subtitle.
        toolbarView.setTitleTextColor(toolbarIconsColor);
        toolbarView.setSubtitleTextColor(toolbarIconsColor);
    }

    public static void doColorizing(View v, final ColorFilter colorFilter, int toolbarIconsColor){
        if(v instanceof ImageButton) {
            ((ImageButton)v).getDrawable().setAlpha(255);
            ((ImageButton)v).getDrawable().setColorFilter(colorFilter);
        }

        if(v instanceof ImageView) {
            ((ImageView)v).getDrawable().setAlpha(255);
            ((ImageView)v).getDrawable().setColorFilter(colorFilter);
        }

        if(v instanceof AutoCompleteTextView) {
            ((AutoCompleteTextView)v).setTextColor(toolbarIconsColor);
        }

        if(v instanceof TextView) {
            ((TextView)v).setTextColor(toolbarIconsColor);
        }

        if(v instanceof EditText) {
            ((EditText)v).setTextColor(toolbarIconsColor);
        }

        if (v instanceof ViewGroup){
            for (int lli =0; lli< ((ViewGroup)v).getChildCount(); lli ++){
                doColorizing(((ViewGroup)v).getChildAt(lli), colorFilter, toolbarIconsColor);
            }
        }

        if(v instanceof ActionMenuView) {
            for(int j = 0; j < ((ActionMenuView)v).getChildCount(); j++) {

                //Step 2: Changing the color of any ActionMenuViews - icons that
                //are not back button, nor text, nor overflow menu icon.
                final View innerView = ((ActionMenuView)v).getChildAt(j);

                if(innerView instanceof ActionMenuItemView) {
                    int drawablesCount = ((ActionMenuItemView)innerView).getCompoundDrawables().length;
                    for(int k = 0; k < drawablesCount; k++) {
                        if(((ActionMenuItemView)innerView).getCompoundDrawables()[k] != null) {
                            final int finalK = k;

                            //Important to set the color filter in seperate thread, 
                            //by adding it to the message queue
                            //Won't work otherwise. 
                            //Works fine for my case but needs more testing

                            ((ActionMenuItemView) innerView).getCompoundDrawables()[finalK].setColorFilter(colorFilter);

//                              innerView.post(new Runnable() {
//                                  @Override
//                                  public void run() {
//                                      ((ActionMenuItemView) innerView).getCompoundDrawables()[finalK].setColorFilter(colorFilter);
//                                  }
//                              });
                        }
                    }
                }
            }
        }
    }



}

그런 다음 레이아웃 파일에서 참조하십시오. 이제 다음을 사용하여 사용자 정의 색상을 설정할 수 있습니다

toolbar.setItemColor(Color.Red);

출처 :

여기에서 정보를 찾았습니다. Android 툴바 아이콘 색상을 동적으로 변경하는 방법

그런 다음 편집하고 개선하여 여기에 게시했습니다. GitHub : AndroidDynamicToolbarItemColor


이것이 당신이 할 수있는 일입니다 :

drawable 폴더에 파일을 작성하고 이름을 background.xml로 지정하십시오.

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <solid android:color="?attr/colorPrimary"/>
</shape>

그런 다음 레이아웃을 설정하십시오 (또는 그와 같은 경우) android:background="@drawable/background"

테마를 설정할 때이 색상은 동일하게 나타납니다.

참고 : https://stackoverflow.com/questions/25815769/how-to-really-programmatically-change-primary-and-accent-color-in-android-loll

반응형