Reputation: 2306
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?
For example, here the color of the status bar and toolbar changes when changing view pager tabs. Thank you in advance.
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>
Upvotes: 14
Views: 8528
Reputation: 16607
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.
Upvotes: 1
Reputation: 3675
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);
}
Upvotes: 5
Reputation: 503
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 :)
Upvotes: 2
Reputation: 503
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));
}
}
Upvotes: 0
Reputation: 1180
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);
}
Upvotes: 4
Reputation: 1499
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.
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 :)
Upvotes: 2