how to change the color of the toolbar and status bar colors according to image color in android material design?

放肆的年华 提交于 2019-12-02 17:18:59

Create your custom themes in style.xml. Then in your menifest set each theme for each activity you want:

style.xml:

<style name="Activity1Theme" parent="MyMaterialTheme.Base">
     <item name="colorPrimary">@color/blue</item>
     <item name="colorPrimaryDark">@color/darkblue</item>
</style>

<style name="Activity2Theme" parent="MyMaterialTheme.Base">
     <item name="colorPrimary">@color/green</item>
     <item name="colorPrimaryDark">@color/darkgreen</item>
</style>

menifest:

<activity
        android:name=".Activity1Theme"
        android:theme="@style/Activity1Theme"></activity>
<activity
        android:name=".Activity2Theme"
        android:theme="@style/Activity2Theme"></activity>

Edit:

If you need to set them for fragments try below code in your fragment:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

// create ContextThemeWrapper from the original Activity Context with the custom theme
final Context contextThemeWrapper = new ContextThemeWrapper(getActivity(), R.style.yourCustomTheme);

// clone the inflater using the ContextThemeWrapper
LayoutInflater localInflater = inflater.cloneInContext(contextThemeWrapper);

// inflate the layout using the cloned inflater, not default inflater
return localInflater.inflate(R.layout.yourLayout, container, false);
}

Use Pallete API

 Palette.from(myBitmap).generate(new Palette.PaletteAsyncListener() {
                @Override
                public void onGenerated(Palette palette) {

                    toolbar.setBackgroundColor(palette.getVibrantColor(getResources().getColor(R.color.primary)));
                    getWindow().setStatusBarColor(palette.getVibrantColor(getResources().getColor(R.color.primary)));
                }
            });

Where myBitmap is the Image from which you want to extract the color. Also for API 21 and above, you'll need to add the following flags if you're planning to color the status bar and navigation bar:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    }
Narayan Acharya

I'm not sure whether you are asking for a programmatic solution to this question or just want to know the steps.

You can do that in basically two steps.

  1. Find the most dominant/prominent colour in the Image.
  2. Get a slightly darker shade of that colour.

These two questions have already been asked and answered on stackoverflow.

For question 1, you can follow https://stackoverflow.com/a/10530562/5512274

For question 2, you can follow https://stackoverflow.com/a/4928826/5512274

All the best :)

I tried this code on Kitkat and worked just fine:

 void getAverageColor(){
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.aaa); //here put your drawable 

        int height=bitmap.getHeight();
        int width=bitmap.getWidth();
        int pixelCount = height * width;
        int[] pixels = new int[pixelCount];
        bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, width, height);

        int redBucket = 0;
        int greenBucket = 0;
        int blueBucket = 0;

        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                int color = pixels[x + y * width];
                redBucket += (color >> 16) & 0xFF; // Color.red
                greenBucket += (color >> 8) & 0xFF; // Color.greed
                blueBucket += (color & 0xFF); // Color.blue
                // does alpha matter?
            }
        }
        String color = String.format("#FF%02x%02x%02x",
                redBucket / pixelCount, greenBucket /pixelCount, blueBucket/pixelCount); //gets the average color in hex form
        setStatusBarColor(findViewById(R.id.statusBarBackground), color);
    }


    public void setStatusBarColor(View statusBar,String color){

        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
           Window w = getWindow();
    w.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    w.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);

            w.setStatusBarColor(Color.parseColor(color));
        } else{
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            Window w =  activity.getWindow();
            w.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            //status bar height
            statusBar.getLayoutParams().height = getStatusBarHeight();
            statusBar.setBackgroundColor(Color.parseColor(color));
        }
    }


    }

    public int getStatusBarHeight() {
        int result = 0;
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }

add this view to xml layout of each activity you want to change the status bar for, this is for pre-lollipop devices:

<View
        android:id="@+id/statusBarBackground"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        />

Of course this is not the only calculation that gets the average color for an image, but I chose it because its simple and easy to understand, it doesnt include the alpha value, you can add an alpha bucket if you need to check the transparency of each pixel. hope this helps.

Edit: also tried it on sdk 5.1 and worked fine :)

for your case all you need to do some changes in the ViewPagerAdapter class, this works for 5.0 sdk and above:

add this to the class:

 String colorArray[]={"ffccff"//color for fragment1,
"#ffffeeff"//color for fragment2,
"#ffeeffee" //color for fragment3,
"#ffeebbcc"//color for fragment4,
"#ffeebbcc" //color for fragment5};

//here put all the colors in hex format for each fragment (in order). //this array must be same size of number of fragments you have

change this method

@Override
    public void onDrawerItemSelected(View view, int position) {
        displayView(position);
    setStatusBarColor(colorArray[position]); //added this line, this will change the status bar depending on the selected fragment
    }

add this code in the end on the ViewpagerAdapter class:

public void setStatusBarColor(String color){

        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
        Window w = getWindow();
        w.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        w.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            w.setStatusBarColor(Color.parseColor(color));
        }
    }

If you want to change color of the Toolbar and StatusBar following step would help you:

1- Add addOnPageChangeListener to your ViewPager.

2- in onPageScrolled call updateBackground

viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                // define two variable in your activity/fragment
                // call them position & positionOffset
                IntroActivity.this.position = (int) Math.floor(position + positionOffset);
                IntroActivity.this.positionOffset = (((position + positionOffset) % 1) + 1) % 1;
                updateBackground();
            }

            @Override
            public void onPageSelected(int position) {

            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });

3- updateBackground would be like following

 private static final int COLOR_PRIMARY[] = {R.color.green_primary, R.color.purple_primary, R.color.red_primary};
 private static final int COLOR_PRIMARY_DARK[] = {R.color.green_primary_dark, R.color.purple_primary_dark, R.color.red_primary_dark};

private void updateBackground() {
        @ColorInt
        int background;
        @ColorInt
        int backgroundNext;
        @ColorInt
        int backgroundDark;
        @ColorInt
        int backgroundDarkNext;

        if (position == adapter.getCount()) {
            background = Color.TRANSPARENT;
            backgroundNext = Color.TRANSPARENT;
            backgroundDark = Color.TRANSPARENT;
            backgroundDarkNext = Color.TRANSPARENT;
        } else {
            background = ContextCompat.getColor(IntroActivity.this,
                    color[(position)]);
            backgroundNext = ContextCompat.getColor(IntroActivity.this,
                    color[(Math.min(position + 1, adapter.getCount() - 1))]);

            background = ColorUtils.setAlphaComponent(background, 0xFF);
            backgroundNext = ColorUtils.setAlphaComponent(backgroundNext, 0xFF);

            try {
                backgroundDark = ContextCompat.getColor(IntroActivity.this,
                        color_darks[(position)]);
            } catch (Resources.NotFoundException e) {
                backgroundDark = ContextCompat.getColor(IntroActivity.this,
                        R.color.mi_status_bar_background);
            }
            try {
                backgroundDarkNext = ContextCompat.getColor(IntroActivity.this,
                        color_darks[(Math.min(position + 1, adapter.getCount() - 1))]);
            } catch (Resources.NotFoundException e) {
                backgroundDarkNext = ContextCompat.getColor(IntroActivity.this,
                        R.color.mi_status_bar_background);
            }
        }

        if (position + positionOffset >= adapter.getCount() - 1) {
            backgroundNext = ColorUtils.setAlphaComponent(background, 0x00);
            backgroundDarkNext = ColorUtils.setAlphaComponent(backgroundDark, 0x00);
        }

        background = (Integer) evaluator.evaluate(positionOffset, background, backgroundNext);
        backgroundDark = (Integer) evaluator.evaluate(positionOffset, backgroundDark, backgroundDarkNext);

        toolbar.setBackgroundColor(background);

        float[] backgroundDarkHsv = new float[3];
        Color.colorToHSV(backgroundDark, backgroundDarkHsv);
        //Slightly darken the background color a bit for more contrast
        backgroundDarkHsv[2] *= 0.95;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            getWindow().setStatusBarColor(backgroundDark);

            if (position == adapter.getCount()) {
                getWindow().setNavigationBarColor(Color.TRANSPARENT);
            } else if (position + positionOffset >= adapter.getCount() - 1) {
                TypedValue typedValue = new TypedValue();
                TypedArray a = obtainStyledAttributes(typedValue.data, new int[]{android.R.attr.navigationBarColor});

                int defaultNavigationBarColor = a.getColor(0, Color.BLACK);

                a.recycle();

                int navigationBarColor = (Integer) evaluator.evaluate(positionOffset, defaultNavigationBarColor, Color.TRANSPARENT);
                getWindow().setNavigationBarColor(navigationBarColor);
            }

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                int systemUiVisibility = getWindow().getDecorView().getSystemUiVisibility();
                int flagLightStatusBar = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
                if (ColorUtils.calculateLuminance(backgroundDark) > 0.4) {
                    //Light background
                    systemUiVisibility |= flagLightStatusBar;
                } else {
                    //Dark background
                    systemUiVisibility &= ~flagLightStatusBar;
                }
                getWindow().getDecorView().setSystemUiVisibility(systemUiVisibility);
            }
        }
    }

Now you have something like this:

4- Just one step remains, in updateBackground instead of COLOR_PRIMARY & COLOR_PRIMARY_DARK, use Pallete to get color of your image.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!