14
votes

I started learning Android material design. I learnt some new features in the lollipop version. Today I am trying to change the color of the tool bar and status bar according to an image's color. Can anyone guide me or provide any links for how to do this?

screenshot

For example, here the color of the status bar and toolbar changes when changing view pager tabs. Thank you in advance. screenshot

styles.xml:

   < style name="MyMaterialTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
            <item name="windowNoTitle">true</item>
            <item name="windowActionBar">false</item>
            <item name="colorPrimary">@color/colorPrimary</item>
            <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
            <item name="colorAccent">@color/colorAccent</item>
        </style>

MainActivity:

public class MainActivity extends AppCompatActivity implements FragmentDrawer.FragmentDrawerListener,FragmentDrawerRight.FragmentDrawerListener1 {

    private static String TAG = MainActivity.class.getSimpleName();


    private Toolbar mToolbar;
    ViewPager viewPager;
    TabLayout tabLayout;
    private FragmentDrawer drawerFragment;
    private FragmentDrawerRight  drawerFragmentRight;
    private ImageView pone,ptwo;
    DrawerLayout drawer_layout;
    int mutedColor;
    private CollapsingToolbarLayout collapsing_toolbar;

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

        collapsing_toolbar  = (CollapsingToolbarLayout)findViewById(R.id.collapsing_toolbar);
        mToolbar = (Toolbar) findViewById(R.id.toolbar);

        setSupportActionBar(mToolbar);

        ptwo=(ImageView)mToolbar.findViewById(R.id.ptwo);


        drawerFragment = (FragmentDrawer)
                getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
        drawerFragmentRight = (FragmentDrawerRight)
                getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer1);

        drawer_layout = (DrawerLayout) findViewById(R.id.drawer_layout);

        drawerFragment.setUp(R.id.fragment_navigation_drawer, drawer_layout, mToolbar);
        drawerFragmentRight.setUp(R.id.fragment_navigation_drawer1, drawer_layout, mToolbar);
        drawerFragment.setDrawerListener(this);
        drawerFragmentRight.setDrawerListener(this);

        viewPager = (ViewPager) findViewById(R.id.viewpager);
        setupViewPager(viewPager);

        tabLayout = (TabLayout) findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(viewPager);

        ptwo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(!drawer_layout.isDrawerOpen(GravityCompat.END)){
                    drawer_layout.openDrawer(GravityCompat.END);
                    drawer_layout.closeDrawer(GravityCompat.START);
                }
            }
        });


    }

    private void setupViewPager(ViewPager viewPager) {
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFrag(new OneFragment(), "ONE");
        adapter.addFrag(new TwoFragment(), "TWO");
        adapter.addFrag(new ThreeFragment(), "THREE");
        adapter.addFrag(new FourFragment(), "FOUR");
        adapter.addFrag(new FiveFragment(), "FIVE");
        adapter.addFrag(new SixFragment(), "SIX");
        adapter.addFrag(new SevenFragment(), "SEVEN");
        adapter.addFrag(new EightFragment(), "EIGHT");
        adapter.addFrag(new NineFragment(), "NINE");
        adapter.addFrag(new TenFragment(), "TEN");
        viewPager.setAdapter(adapter);
    }

    class ViewPagerAdapter extends FragmentPagerAdapter {
        private final List<Fragment> mFragmentList = new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();

        public ViewPagerAdapter(FragmentManager manager) {
            super(manager);
        }

        @Override
        public Fragment getItem(int position) {
            return mFragmentList.get(position);
        }

        @Override
        public int getCount() {
            return mFragmentList.size();
        }

        public void addFrag(Fragment fragment, String title) {
            mFragmentList.add(fragment);
            mFragmentTitleList.add(title);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return mFragmentTitleList.get(position);
        }
    }

    @Override
    public void onDrawerItemSelected(View view, int position) {
        displayView(position);
    }

    private void displayView(int position) {
        viewPager.setCurrentItem(position);
        getSupportActionBar().setTitle(getResources().getStringArray(R.array.nav_drawer_labels)[position]);
    }

    private void displayView1(int position) {
        Fragment fragment = null;
        String title = getString(R.string.app_name);
        switch (position) {
            case 0:
                fragment = new OneFragment();
                title = getString(R.string.title_home);
                break;
            case 1:
                fragment = new TwoFragment();
                if (Build.VERSION.SDK_INT >= 21) {
                    getWindow().setNavigationBarColor(getResources().getColor(R.color.colorAccent));

                }
                title = getString(R.string.title_friends);


                break;
            case 2:
                fragment = new ThreeFragment();
                title = getString(R.string.title_messages);
                break;
            case 3:
                fragment = new FourFragment();
                title = getString(R.string.title_home);
                break;
            case 4:
                fragment = new FiveFragment();
                title = getString(R.string.title_friends);
                break;
            case 5:
                fragment = new SixFragment();
                title = getString(R.string.title_messages);
                break;
            default:
                break;
        }

        if (fragment != null) {

            getSupportActionBar().setTitle(title);
        }
    }
}

activty_main:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

            <android.support.design.widget.CollapsingToolbarLayout
                android:id="@+id/collapsing_toolbar"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                app:contentScrim="?attr/colorPrimary"
                app:expandedTitleMarginBottom="32dp"
                app:expandedTitleMarginEnd="64dp"
                app:expandedTitleMarginStart="48dp"
                app:layout_scrollFlags="scroll|exitUntilCollapsed">
                <ImageView
                    android:id="@+id/header"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:background="@drawable/ic_profile"
                    android:fitsSystemWindows="true"
                    android:scaleType="centerCrop"
                    app:layout_collapseMode="parallax" />
                <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    android:background="?attr/colorPrimary"
                    app:layout_scrollFlags="scroll|enterAlways"
                    app:popupTheme="@style/ThemeOverlay.AppCompat.Light" >
                    <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:paddingRight="15dp">

                        <TextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_gravity="center_vertical"
                            android:gravity="center"
                            android:visibility="invisible"
                            android:textSize="20sp"
                            android:textColor="@android:color/white"
                            android:layout_weight="1"
                            android:text="Reload"
                            />
                        <ImageView
                            android:id="@+id/ptwo"
                            android:layout_width="25dp"
                            android:layout_height="25dp"
                            android:layout_gravity="right|center_vertical"
                            android:src="@drawable/ic_profile"/>
                    </LinearLayout>

                </android.support.v7.widget.Toolbar>
            </android.support.design.widget.CollapsingToolbarLayout>




            <android.support.design.widget.TabLayout
                android:id="@+id/tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:tabMode="scrollable"/>
        </android.support.design.widget.AppBarLayout>

        <android.support.v4.view.ViewPager
            android:id="@+id/viewpager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />
        <!--<LinearLayout
            android:id="@+id/container_toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <include
                android:id="@+id/toolbar"
                layout="@layout/toolbar" />
        </LinearLayout>

        <FrameLayout
            android:id="@+id/container_body"
            android:layout_width="fill_parent"
            android:layout_height="0dp"
            android:layout_weight="1" />
-->

    </LinearLayout>


    <fragment
        android:id="@+id/fragment_navigation_drawer"
        android:name="info.androidhive.materialdesign.activity.FragmentDrawer"
        android:layout_width="@dimen/nav_drawer_width"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:layout="@layout/fragment_navigation_drawer"
        tools:layout="@layout/fragment_navigation_drawer" />
    <fragment
        android:id="@+id/fragment_navigation_drawer1"
        android:name="info.androidhive.materialdesign.activity.FragmentDrawerRight"
        android:layout_width="@dimen/nav_drawer_width"
        android:layout_height="match_parent"
        android:layout_gravity="end"
        app:layout="@layout/fragment_navigation_drawer_right"
        tools:layout="@layout/fragment_navigation_drawer_right" />






</android.support.v4.widget.DrawerLayout>

OneFragment:

public class OneFragment extends Fragment {

 public HomeFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_home, container, false);


        // Inflate the layout for this fragment
        return rootView;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
    }

    @Override
    public void onDetach() {
        super.onDetach();
    }
}

fragment_home.xml:

<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:orientation="vertical"
    tools:context="info.androidhive.materialdesign.activity.HomeFragment">


    <TextView
        android:id="@+id/label"
        android:layout_alignParentTop="true"
        android:layout_marginTop="100dp"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:textSize="45dp"
        android:text="HOME"
        android:textStyle="bold"/>

    <TextView
        android:layout_below="@id/label"
        android:layout_centerInParent="true"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textSize="12dp"
        android:layout_marginTop="10dp"
        android:gravity="center_horizontal"
        android:text="Edit fragment_home.xml to change the appearance" />

</RelativeLayout>

colors.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#303f95</color>
    <color name="colorPrimaryDark">#3f5185</color>
    <color name="textColorPrimary">#FFFFFF</color>
    <color name="windowBackground">#FFFFFF</color>
    <color name="navigationBarColor">#000000</color>
    <color name="colorAccent">#FF80AB</color>
    <color name="colorAccentt">#b6b6b6</color>
    <color name="primary">@color/blue_500</color>
    <color name="primaryDark">@color/blue_700</color>
    <color name="textPrimary">@color/text_white_text_icons_100</color>
</resources>
6
Maybe you are looking for Palette API to get bitmap colors?Louis CAD
Searching for "Palette API", and "Palette API examples" on Google should help youLouis CAD

6 Answers

4
votes

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);
}
4
votes

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);
    }
2
votes

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 :)

2
votes

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 :)

0
votes

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));
        }
    }
0
votes

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:

enter image description here

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