I am implementing Toolbar along and Navigation drawer.I am customized my tool bar with my own views.I have my own menu(Hamburger) icon in my toolbar to open navigation drawer and I am showing badge count on my menu icon(Hamburger).So i would like to hide default Hamburger icon.
I have tried like this:
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
getSupportActionBar().setDefaultDisplayHomeAsUpEnabled(false);
Please help me.Thanks in advance.
call .setDrawerIndicatorEnabled(false); on your ActionBarDrawerToggle
This works for me:
public void setLogo(String imageUrl) {
ViewGroup toolbarView = (ViewGroup) toolbar.findViewById(R.id.toolbar);
// set an arbitrary logo so the support library adds an ImageView to the toolbar.
// without this, there would be no ImageView elements in the toolbar
// and the following loop would not work
// `empty_drawable` is a simple rectangle of size 100x100 with a bg color
// matching that of the toolbar
// the size really matters because the smaller you set this image, the next logo
// you set will be of that size. If your arbitrary drawable is of size 1x1, then
// the next logo you set will be of the same size. At least that is what happens
// for me when I load an image with Glide.
// Your drawable should have a background color too. I chose the toolbar's
// background color. If you don't set a background color, your app would crash on Kitkat.
toolbar.setLogo(R.drawable.empty_drawable);
for (int i = 0; i < toolbarView.getChildCount(); i++) {
if ((toolbarView.getChildAt(i) instanceof ImageView)) {
ImageView logoView = (ImageView) toolbarView.getChildAt(i);
if (!TextUtils.isEmpty(imageUrl)) {
// this way I can download an image and set the logo that way
Glide.with(MainActivity.this).load(imageUrl).into(logoView);
// I do this because there is no space between logo and the toolbar title
logoView.setPadding(0, 0, 30, 0);
// and this is because of the `else` block
logoView.setVisibility(View.VISIBLE);
} else {
// pass null to `setLogo()` to hide the logo
logoView.setVisibility(View.GONE);
logoView.setPadding(0, 0, 0, 0);
}
break;
}
}
}
And this is my toolbar:
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:animateLayoutChanges="true"
app:popupTheme="#style/AppTheme.PopupOverlay"
app:title="#string/app_name"
tools:ignore="UnusedAttribute" />
The android:animateLayoutChanges="true" part makes all this really nice.
And tools:ignore="UnusedAttribute" is because my app's minimum SDK is set to 9.
Try this in your activity's onCreate:
getActionBar().setIcon(
new ColorDrawable(getResources().getColor(android.R.color.transparent)));
If you're using the AppCompat, replace getActionBar with getSupportActionBar.
Related
I have a screen in my app that loads an image behind a transparent status bar. Sometimes these images are light enough for the status bar icons and text to get lost in the image.
How do you set the status bar to light/dark based on the colors of the image underneath it? I'm trying to keep the status bar completely transparent and not add a background.
You can use this solution to change the statusbar color based on your background :
// Set the background and text colors of a toolbar given a
// bitmap image to match
public void setToolbarColor(Bitmap bitmap) {
// Generate the palette and get the vibrant swatch
// See the createPaletteSync() method
// from the code snippet above
Palette p = createPaletteSync(bitmap);
Palette.Swatch vibrantSwatch = p.getVibrantSwatch();
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
// Load default colors
int backgroundColor = ContextCompat.getColor(getContext(),
R.color.default_title_background);
int textColor = ContextCompat.getColor(getContext(),
R.color.default_title_color);
// Check that the Vibrant swatch is available
if(vibrantSwatch != null){
backgroundColor = vibrantSwatch.getRgb();
textColor = vibrantSwatch.getTitleTextColor();
}
// Set the toolbar background and text colors
toolbar.setBackgroundColor(backgroundColor);
toolbar.setTitleTextColor(textColor);
}
Now, simply generate bitmap from your background and then use it with this method.
For more info, visit the official developers site - Color palette API
I have been looking for answers on how to place the indeterminate horizontal progress bar below the action bar using AppCompat. I'm able to get the horizontal progress bar to appear, but it is at the top of the action bar. I want it under/below the action bar kind of like how gmail does it (except without the pull to refresh).
I used the following code to have the progress bar appear:
supportRequestWindowFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.main_activity);
setSupportProgressBarIndeterminate(Boolean.TRUE);
setSupportProgressBarVisibility(true);
but this places the horizontal progress bar at the top of the action bar. Anyone know how to place the progress bar below the action bar?
I faced a similar problem recently and solved it by creating my own progressbar and then aligning it by manipulating getTop() of the content view.
So first create your progressbar.
final LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, 20); //Use dp resources
mLoadingProgressBar = new ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal);
mLoadingProgressBar.setIndeterminate(true);
mLoadingProgressBar.setLayoutParams(lp);
Add it to the window (decor view)
final ViewGroup decor = (ViewGroup) getWindow().getDecorView();
decor.addView(mLoadingProgressBar);
And in order to get it to its correct position Im using a ViewTreeObserver that listens until the view has been laid out (aka the View.getTop() isnt 0).
final ViewTreeObserver vto = decor.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
final View content = getView(android.R.id.content);
#Override
public void onGlobalLayout() {
int top = content.getTop();
//Dont do anything until getTop has a value above 0.
if (top == 0)
return;
//I use ActionBar Overlay in some Activities,
//in those cases it's size has to be accounted for
//Otherwise the progressbar will show up at the top of it
//rather than under.
if (getSherlock().hasFeature((int) Window.FEATURE_ACTION_BAR_OVERLAY)) {
top += getSupportActionBar().getHeight();
}
//Remove the listener, we dont need it anymore.
Utils.removeOnGlobalLayoutListener(decor, this);
//View.setY() if you're using API 11+,
//I use NineOldAndroids to support older
ViewHelper.setY(mLoadingProgressBar, top);
}
});
Hope that makes sense for you. Good luck!
Question Summary: How can I make a ProgressBar integrated inside the ActionBar, like on the Chrome App?
Details: Look at this screenshot from Chrome:
I want to create an Action Bar just like this. Just under the Action Bar, there's a ProgressBar that fills according to page load. I've seen this example from many apps, like Feedly, but I haven't been able to create my own implementation. I tried using Android's own APIs to create it:
#Override
protected void onCreate(Bundle savedInstanceState) {
//Request Permission to display the Progress Bar...
this.requestWindowFeature(Window.FEATURE_PROGRESS);
this.setWindowContentView(R.layout.activity_main)
super.onCreate(savedInstanceState);
this.setProgressBarIndeterminate(true);
}
But this code only causes the ProgressBar to show over the Action Bar, like so:
So, how can I make my ProgressBar appear under the Action Bar, like on the Chrome App?
I wasn't fully satisfied with the accepted answer above, so I did some extra research myself.
The trick I believe they used is that they retrieved the top view in the view hierarchy called DecorView and added the progress bar in there. That way, the progress bar displays both over the action bar AND the content area. Note that the S.D.'s answer puts the progress bar into content area and 'steals' space from actual content, what can lead to unexpected results.
Sample screenshots of this implementation:
Code
Just put this code into onCreate method of some activity and it should work:
// create new ProgressBar and style it
final ProgressBar progressBar = new ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal);
progressBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 24));
progressBar.setProgress(65);
// retrieve the top view of our application
final FrameLayout decorView = (FrameLayout) getWindow().getDecorView();
decorView.addView(progressBar);
// Here we try to position the ProgressBar to the correct position by looking
// at the position where content area starts. But during creating time, sizes
// of the components are not set yet, so we have to wait until the components
// has been laid out
// Also note that doing progressBar.setY(136) will not work, because of different
// screen densities and different sizes of actionBar
ViewTreeObserver observer = progressBar.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
View contentView = decorView.findViewById(android.R.id.content);
progressBar.setY(contentView.getY() - 10);
ViewTreeObserver observer = progressBar.getViewTreeObserver();
observer.removeOnGlobalLayoutListener(this);
}
});
You can play with LayoutParams' height argument to set the progressBar wider or narrower, but you might have to adjust the -10 offset.
Styling
Unfortunately, you can see the ugly gray background of the progress bar. To remove it, simply searching for the background by id and trying to hide it doesn't work. To remove the background, I had to create identical drawble of the system version and remove the background item.
TL;DR: Create file progress_horizontal_holo_no_background_light.xml and paste this drawable:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/secondaryProgress">
<scale android:scaleWidth="100%"
android:drawable="#drawable/progress_secondary_holo_light" />
</item>
<item android:id="#android:id/progress">
<scale android:scaleWidth="100%"
android:drawable="#drawable/progress_primary_holo_light" />
</item>
</layer-list>
Copy appropriate .png drawables from sdk/platforms/android-xx/data/res/drawable-xxx/ to your project and then in the code you can add:
progressBar.setProgressDrawable(getResources().getDrawable(R.drawable.progress_horizontal_holo_no_background_light));
Extra: Indeterminate Progress Bar
Pre-KitKat versions of indeterminate progress bars are pretty ugly and laggy.
You can download new smooth progressBar called ButteryProgressBar. Just search for it on google (I cannot post any more links, because I am new here :[ ), add the class into your project and you can simply replace the previous ProgressBar with this code and have crispy indeterminate progress bar:
final ButteryProgressBar progressBar = new ButteryProgressBar(this);
progressBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 24));
You might also need to simplify this code:
final TypedArray ta = c.obtainStyledAttributes(attrs, R.styleable.ButteryProgressBar);
try {
mBarColor = ta.getColor(R.styleable.ButteryProgressBar_barColor,
c.getResources().getColor(android.R.color.holo_blue_light));
mSolidBarHeight = ta.getDimensionPixelSize(
R.styleable.ButteryProgressBar_barHeight,
Math.round(DEFAULT_BAR_HEIGHT_DP * mDensity));
mSolidBarDetentWidth = ta.getDimensionPixelSize(
R.styleable.ButteryProgressBar_detentWidth,
Math.round(DEFAULT_DETENT_WIDTH_DP * mDensity));
} finally {
ta.recycle();
}
to this code:
mBarColor = c.getResources().getColor(android.R.color.holo_blue_light);
mSolidBarHeight = Math.round(DEFAULT_BAR_HEIGHT_DP * mDensity);
mSolidBarDetentWidth = Math.round(DEFAULT_DETENT_WIDTH_DP * mDensity);
Hope I helped :)
Extend Activities from following class to have a ProgressBar at the top(below ActionBar) of each, and a getProgressBar() method:
Parent class:
public abstract class ProgressActivity extends Activity {
private ProgressBar mProgressBar;
#Override
public void setContentView(View view) {
init().addView(view);
}
#Override
public void setContentView(int layoutResID) {
getLayoutInflater().inflate(layoutResID,init(),true);
}
#Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
init().addView(view,params);
}
private ViewGroup init(){
super.setContentView(R.layout.progress);
mProgressBar = (ProgressBar) findViewById(R.id.activity_bar);
return (ViewGroup) findViewById(R.id.activity_frame);
}
protected ProgressBar getProgressBar(){
return mProgressBar;
}
}
Layout (progress.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
android:layout_width="match_parent" android:layout_height="match_parent">
<ProgressBar android:id="#+id/activity_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="-8dp"
style="#android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
/>
<FrameLayout android:id="#+id/activity_frame"
android:layout_width="match_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
This is now a native behavior that can be obtained using SwipeRefreshLayout.
You can wrap your scrollable view with a SwipeRefreshLayout and then you just need to listen to onRefresh events:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
swipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
swipeLayout.setOnRefreshListener(this);
swipeLayout.setColorScheme(android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
}
#Override public void onRefresh() {
new Handler().postDelayed(new Runnable() {
#Override public void run() {
swipeLayout.setRefreshing(false);
}
}, 5000);
}
A nice and simple tutorial can be found in this blog.
I have compiled code from this thread as well as other threads on StackOverflow and created a project that can be used to implement ButteryProgessbar as well as "pull down to refresh". https://github.com/pauldmps/Gmail-like-Pull-Down-to-Refresh
Feel free to use the code in your application.
A big thanks to you guys.
Please use below code. just use one default style in progress bar as style="?android:attr/progressBarStyleHorizontal"
<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"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
<ProgressBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?android:attr/progressBarStyleHorizontal"
android:indeterminate="true"
/>
</RelativeLayout>
Well , I did something similar for one of my pet apps and am not sure if that's the only way or the best way to do it , but it definitely works.
To begin with , use an overlay action bar and then set the background drawable to "null" so that the overlay action bar is transparent.
Now in you activity layout , set the top margin for your root view to "actionbar height" You can do it like this.
<RelativeLayout
...
android:layout_marginTop="?android:attr/actionBarSize" />
Now the action is not going to hide any of your activity content.
The next thing you have to do now is - add a header view on top of your root view with height same as the action bar. Set a background color to it. This would now be the color of your action bar and since the action bar aligns perfectly on top pf this header view.
Now you can easily put a progress bar in the header view and align it to the bottom of the header view. To the user this would look as if the progress bar is on the action bar itself , just like chrome ..
I'm currently making one of my very first applications. I'm using ActionBarSherlock.
I would like to make my logo overlap the actionbar (scrollview).
Currently I have main_activity.xml. In MainActivity.java I use setContentView to view main_activity.xml. After that I use getSupportActionBar() for ActionBarSherlock. I've tried things out using RelativeLayout (http://www.mkyong.com/android/android-relativelayout-example/). That didn't really work because there are multiple layouts.
So I've tried some things right and left, but it always ends up infront or behind the actionbar, or stops just before reaching the content. It's because of two different layouts, that's what I know. But how can I going to solve this? Is it possible? Thanks in advance!
What I want:
http://f.cl.ly/items/3N0w243N1t2Q3i1H1f1k/Untitled-1.png
You can either:
A. Split your image in two
Have the top part as the ActionBar logo, then show the bottom part over your content.
B. Use a single image
You'll need a layout file that contains just your logo (you'll probably want something like an ImageView inside a LinearLayout so you can easily set the correct margins).
Then after calling setContentView for your activity, add your logo view with:
ViewGroup decorViewGroup = (ViewGroup) getWindow().getDecorView();
decorViewGroup.addView(logoView);
Using a layout file
Example layout file (logo_view.xml):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/logo_image"
android:scaleType="center"
android:layout_marginLeft="10dip"
/>
</LinearLayout>
Inflate the layout file:
LayoutInflater inflater = LayoutInflater.from(this);
View logoView = inflater.inflate(R.layout.logo_view, null, false);
Although the original answer works on some devices, on others the image sits under the status bar. I resolved this by getting the location of the top ActionBar and comparing it to the location of the top of the logo image and then just adding some top padding, as follows:
// Inflate logo layout
LayoutInflater inflater = LayoutInflater.from(this);
final View logoView = inflater.inflate(R.layout.menu_logo, null);
// Add logo to view
ViewGroup viewGroup = (ViewGroup) getWindow().getDecorView();
viewGroup.addView(logoView);
// Adjust the logo position
int resId = getResources().getIdentifier("action_bar_container", "id", "android");
final View actionBarView = viewGroup.findViewById(resId);
if (actionBarView != null) {
actionBarView.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
// Remove the listener
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
actionBarView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
actionBarView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
// Measure views
int[] location = new int[2];
actionBarView.getLocationOnScreen(location);
int[] logoLocation = new int[2];
logoView.getLocationOnScreen(logoLocation);
// Add top padding if necessary
if (location[1] > logoLocation[1]) {
logoView.setPadding(0, location[1] - logoLocation[1], 0, 0);
}
}
}
);
}
This worked on a wide range of devices (phones, big/small tablets - inc Kindle Fire HDX) running Android versions 4.0 up to 4.4.4 as well as Android L preview.
I'm using a custom view for the ActionBar with Tabs. My problem is the ordering of the custom view. Android is displaying it AFTER the tabs - which I do not want.
I want the custom view displayed BEFORE the tabs.
Is there a way to customize the actionBar to show the custom view before the tabs? or is this not possible?
Code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ActionBar bar = getActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
View customActionBarView =
getLayoutInflater().inflate(R.layout.home_actionbar, null, true);
ActionBar.LayoutParams lp =
new ActionBar.LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.START;
bar.setCustomView(customActionBarView, lp);
bar.setLogo(R.drawable.logo);
bar.setHomeButtonEnabled(true);
bar.setDisplayShowCustomEnabled(true);
bar.addTab(bar.newTab()
.setText("Stuff")
.setTabListener(new TabListener<StuffFragment>(
this, "stuff", StuffFragment.class)));
bar.addTab(bar.newTab()
.setText("Friends")
.setTabListener(new TabListener<ContactsFragment>(
this, "friends", ContactsFragment.class)));
bar.addTab(bar.newTab()
.setText("Messages")
.setTabListener(new TabListener<ConversationsFragment>(
this, "messages", ConversationsFragment.class)));
if (savedInstanceState != null) {
bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
}
bar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM |
ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_USE_LOGO);
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
}
This seems to be the intended behaviour when using tabs and custom views.
https://code.google.com/p/android/issues/detail?id=36191#c3
If you take a look at ActionBarSherlock - Tabs appearing ABOVE actionbar with custom view many other people are experiencing this as well and some people have offered solutions.
I have been unable to get any of the solutions working, but they may work for you. The trick seems to be to make sure the logo is is not set to be hidden. Call
getActionBar().setDisplayShowHomeEnabled(true) or getSupportActionBar().setDisplayShowHomeEnabled(true) if using ActionBarSherlock.
Then call:
View homeIcon = findViewById(
Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ?
android.R.id.home : R.id.abs__home);
((View) homeIcon.getParent()).setVisibility(View.GONE);
((View) homeIcon).setVisibility(View.GONE);
This will get a reference to the actionbar view that holds the logo and sets it to gone with enables the custom view to fill the entire parent view, but should keep the tabs underneath...
As I said I was unable to get this working, but some people have had success.
Good luck.
I had the same problem and i figured out a way to solve it.
It's not an "elegant" solution but it was the best i could find.
As first thing since you want to modify the standard ActionBar behaviour you have to force ActionBar Sherlok to always use the non native implementation.
To do that open ActionBarSherlok.java and comment this line of code:
registerImplementation(ActionBarSherlockNative.class);
then remove all the values-v11 values-v14 etc and be sure to always extend Theme.Sherlock and never Theme.Holo
At this point you are sure that the ActionBar implementation is always the one written by Jake Wharton.
The only thing left to do is make the ActionBar view layout the way you want.
Open ActionBarView.java and in the onLayout() method move this piece of code
if (mExpandedActionView == null) {
final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
(mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
if (showTitle) {
x += positionChild(mTitleLayout, x, y, contentHeight);
}
switch (mNavigationMode) {
case ActionBar.NAVIGATION_MODE_STANDARD:
break;
case ActionBar.NAVIGATION_MODE_LIST:
if (mListNavLayout != null) {
if (showTitle) x += mItemPadding;
x += positionChild(mListNavLayout, x, y, contentHeight) + mItemPadding;
}
break;
case ActionBar.NAVIGATION_MODE_TABS:
if (mTabScrollView != null) {
if (showTitle) x += mItemPadding;
x += positionChild(mTabScrollView, x, y, contentHeight) + mItemPadding;
}
break;
}
}
right before this piece
if (mProgressView != null) {
mProgressView.bringToFront();
final int halfProgressHeight = mProgressView.getMeasuredHeight() / 2;
mProgressView.layout(mProgressBarPadding, -halfProgressHeight,
mProgressBarPadding + mProgressView.getMeasuredWidth(), halfProgressHeight);
}
You're done!
Hope this helps
When you add your custom view to the ActionBar you can specify the gravity also.
ActionBar.LayoutParams lp = new ActionBar.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.LEFT;
customView.setLayoutParams(lp);
use ActionBarSherlock, which is very good implementation of Custom ActionBar for all android versions and very easy to use.
or you can create your own ActionBar using custom title bar and and its fair enough easy to implement. You can see this and this examples are very good examples of custom title bars.
Are you making an app for the tablet? As far as I know, the tabs bar of actionbar basically appears below the it on cellphone.
If on tablet, I'm afraid you can't adjust the positions of tabs. what I can think of is that you need to quit using navigation mode and make a custom view which look like tabs to replace the actionBar tabs. Of course this causes a lot of extra effort to deal with the navigation stuff.
Just create a custom view for your home button. In this view you can combine both logo and the custom view you're trying to position on left. Then add tabs as normal
The only downside of this solution is that you'll need to maintain the state of the back button yourself (if you use it at all)
First set "DisplayShowHomeEnabled" property of actionbar to "true":
actionBar.setDisplayShowHomeEnabled(true);
and then:
View homeIcon = findViewById(android.R.id.home);
((View) homeIcon.getParent()).setVisibility(View.GONE);
((View) homeIcon).setVisibility(View.GONE);
I hope it helps :)