I have searched more than 100 links but haven't found any working answer to the question.
I need to create variable number of tabs depending on the number of tabs I receive from previous activity. The tabs I get can have a length from 3 characters (All) to 24 characters. I am using the attached code for creating the tabs.
final ActionBar actionBar = getActionBar();
actionBar.setDisplayShowHomeEnabled(false);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayHomeAsUpEnabled(false);
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setCustomView(actionBarLayout);
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
final int actionBarColor = getResources().getColor(R.color.green);
actionBar.setBackgroundDrawable(new ColorDrawable(actionBarColor));
for(int k = 0; k < tabs.length; k++) {
TextView t = new TextView(browse_sub_category);
t.setText(tabs[k]);
t.setTextSize(18);
t.setGravity(Gravity.CENTER);
t.setSingleLine();
t.setPadding(0, 20, 0, 0);
t.setTypeface(myTypefaceLight);
t.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
actionBar.addTab(
actionBar.newTab()
.setCustomView(t)
.setTabListener(browse_sub_category));
}
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
By using the setCustomView, I can customize the textview but that doesn't impact the width of my tab. It is taking the default width. I want that if my tab name say 'All' require only 40dp to fit in then it should take only 40dp and if my tab name say 'Hello World' require 120dp then the tab should automatically take that width.
I have already tried customizing the textview by changing the width from LayoutParams.WRAP_CONTENT to numeric values. I have also tried to put a check like
if(tabs[k].length() <= 3) {
tabWidth=40;
} else if((tabs[k].length() > 3) && (tabs[k].length() <= 6) {
tabWidth=80;
} else {
tabWidth=120;
}
but this impacts only the width textview not the width of tab.
I can set the maximum and minimum width of tab in styles.xml but that doesn't provide me the freedom to customize tab width based on tab name.
Any help would be really appreciated.
Related
I want to disable actionBar when the layout is changed for smaller devices but I dont know how to do it. Probably I will do
ActionBar actionBar = getSupportActionBar();
actionBar.hide();
but how to check the layout?
Its simple you can use this example to get the size of the screen and then hide the ActionBar if needed.
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
double x = Math.pow(dm.widthPixels/dm.xdpi,2);
double y = Math.pow(dm.heightPixels/dm.ydpi,2);
double screenInches = Math.sqrt(x+y);
it will get you the size of the screen in inches. and if you want it in pixels then you can use
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
Hope it helps
There are a number of options in this situation.
Firstly, are you sure that your application will be useable without an action bar? e.g. Why do you need an action bar on large devices when you can do without it on smaller devices?
Are you using the Android Toolbar (Which I recommend)? If so you can choose not to include the toolbar in your layout for the smaller screen in your layout xml files. e.g. Include the toolbar in layout-large directory and exclude it from layout-small. Then when you bind the views in your activity/fragment handle the case where the toolbar view is not found.
Toolbar toolbar = (Toolbar)findViewById(R.id.myToolbar);
if(toolbar != null) {
//set up my toolbar here which might include
setSupportActionBar(toolbar);
}
Another option is to use multiple styles for different size screens. Where for the large screen your style is Theme.AppCompat.Light.DarkActionBar and for your small screen its Theme.AppCompat.Light.NoActionBar
Probably your best approach is to make a copy of your style.xml of the res/values to the res/values-mdpi (or your desired layout size) and change the AppTheme to your style + .NoActionBar.
Example:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
If you want to check which layout was loaded you can add tags to your layout for example:
ldpi layout:
<RelativeLayout
android:width="match_parent"
android:height="match_parent"
android:id="#+id/mainlayout"
android:tag="ldpi" >
mdpi layout:
<RelativeLayout
android:width="match_parent"
android:height="match_parent"
android:id="#+id/mainlayout"
android:tag="mdpi" >
and so on.
In your program code you can now check which tag the layout have:
RelativeLayout layout = (RelativeLayout) findViewById(R.id.mainlayout);
String tag = layout.getTag();
if(tag != null && tag.equals("ldpi")) {
// Ldpi Layout loaded, hide actionbar
}
Use DisplayMetrics
public void setAppInvisible() {
actionBar.setVisibility(View.INVISIBLE);
// Or actionBar.hide();
}
DisplayMetrics dm = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
int screenWidth = dm.widthPixels;
if(screenWidth < 500){
setAppInvisible();
}
I am currently developing an application in which I use a heavily modified Split Action Bar. Here is a link to the app's current state:
You'll notice a transparent action bar up top, with a custom view inflated into it, with a hacked together split action bar on bottom. The bottom view is actually a single action item with a custom view inflated into it and showAlways=true.
Currently I only support SDK v15+ and I don't really plan on changing that, but with the Lollipop AppCompat library that just released, I decided to implement it, so I could get some of that awesomeness in my app.
I've changed my theme to Theme.AppCompat.Light, and my MainActivity now extends ActionBarActivity instead of Activity.
All references to getActionBar have now been switched to getSupportActionBar, and with only those changes, this is what my activity now looks like:
You'll notice I got a UI dump from the Device Monitor, and it's shoving the bottom action bar into a weird space and calling that the action bar, and getting rid of my top custom view.
Here is my code for setting up my action bar:
public void initializeActionBar(){
View customNav = LayoutInflater.from(this).inflate(R.layout.action_bar_top, null);
actionBar = getSupportActionBar();
actionBar.setBackgroundDrawable(getResources().getDrawable(R.drawable.transparent_fifty_percent));
final PopupWindow window = addPopupWindow();
actionBarOptions = (ImageView)customNav.findViewById(R.id.options);
actionBarOptions.setVisibility(View.GONE);
actionBarOptions.setImageDrawable(app.svgToBitmapDrawable(getResources(), R.raw.vertical_ellipsis, app.scaleByDensity(48)));
actionBarOptions.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
window.showAsDropDown(actionBarOptions, 0, 0);
}
});
TextView title = (TextView) customNav.findViewById(R.id.screen_title);
Typeface font1 = Typeface.createFromAsset(getAssets(), "Merriweather-Italic.ttf");
title.setText("Parsley");
title.setTypeface(font1);
actionBar.setCustomView(customNav);
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayShowHomeEnabled(false);
actionBar.setDisplayUseLogoEnabled(false);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
new MenuInflater(this).inflate(R.menu.test, menu);
LinearLayout fullMenu = (LinearLayout) menu.findItem(R.id.full_menu).getActionView();
ViewGroup.LayoutParams params;
icon1 = (ImageView) fullMenu.findViewById(R.id.action_item1);
params = icon1.getLayoutParams();
params.width = getResources().getDisplayMetrics().widthPixels / 4;
params.height = (int) (48 * getResources().getDisplayMetrics().density);
icon1.setImageDrawable(app.svgToBitmapDrawable(getResources(), R.raw.shopping_list_icon, app.scaleByDensity(32)));
icon2 = (ImageView) fullMenu.findViewById(R.id.action_item2);
icon3 = (ImageView) fullMenu.findViewById(R.id.action_item3);
icon4 = (ImageView) fullMenu.findViewById(R.id.action_item4);
icon2.setImageDrawable(app.svgToBitmapDrawable(getResources(), R.raw.recipe_box_icon, app.scaleByDensity(32)));
icon3.setImageDrawable(app.svgToBitmapDrawable(getResources(), R.raw.icon_search, app.scaleByDensity(32)));
icon4.setImageDrawable(app.svgToBitmapDrawable(getResources(), R.raw.icon_add, app.scaleByDensity(32)));
params = icon2.getLayoutParams();
params.width = getResources().getDisplayMetrics().widthPixels / 4;
params.height = (int) (48 * getResources().getDisplayMetrics().density);
params = icon3.getLayoutParams();
params.width = getResources().getDisplayMetrics().widthPixels / 4;
params.height = (int) (48 * getResources().getDisplayMetrics().density);
params = icon4.getLayoutParams();
params.width = getResources().getDisplayMetrics().widthPixels / 4;
params.height = (int) (48 * getResources().getDisplayMetrics().density);
if (!firstLoad) {
setBottomActionBarActive();
setActiveTab(0);
}
optionsLoaded = true;
return true;
}
initializeActionBar() is called from onCreate in my activity. Any ideas what I'm doing wrong?
Toolbar should be used. In your case it's one toolbar at the top, and one at the bottom. Check android team blog, they have nice integration guide.
If you just want your bottom action bar back, you can simply change back to appcompat v7:20 ,and it works for me. The problem is split action bar is no longer being supported in appcomat v7:21.
While user482277's solution may work for instances with a more traditional split action bar, utilizing action items, navigation drawer, etc, it didn't quite work for me. What I ended up doing was building a pair of custom (compound really) views to emulate both the top and bottom action bar. I found this situation to work much better, especially with backwards compatibility. I don't have to worry about earlier versions supporting action bar, because at the end of the day, it's just a pair of classes that extend LinearLayout. In addition, I don't have to worry about different screen sizes (particularly tablets) not supporting the split version.
I am using different layout for action bar and add different items to it that matched to my requirements. and then calling it in java class like this
ActionBar actionBar = getActionBar();
actionBar.setCustomView(R.layout.actionbar);
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
actionBar.setDisplayShowHomeEnabled(false);
It looks fine for 2 or 3 different devices but doesn't look compatible for nexus7 tablet and xhdpi. The height of action bar is small for that and it gives empty space.What should I do to manage this? I am using
android:layout_width="match_parent"
android:layout_height="48dp"
in actionbar layout.I have also used
android:layout_height="wrap_content"
but it doesn't work at all.I don't know how to fix it. Please help.
You can set the height of the action bar at source not in the resources.
so all you need is to calculate the height of the action bar :
TypedValue tv = new TypedValue();
if (getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true))
{
actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());
}
ActionBar bar = getSupportActionBar();
Display d = getWindowManager().getDefaultDisplay();
DisplayMetrics dm = new DisplayMetrics();
d.getMetrics(dm);
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)myCustomView.getLayoutParams();
final int ACTION_BAR_HEIGHT = dm.heightPixels/10; // 1/10 from screen height
lp.height = ACTION_BAR_HEIGHT;
myCustomView.setLayoutParams(lp);
bar.setCustomView(myCustomView);
I have created four tabs but want each tab to be a different block color - should this be done in the xml or java file? I'm assuming java because I only have one xml file for the whole tab widget.
try to customise the individual tabs
try using something like
TabWidget tabWidget = getTabWidget();
for(int i = 0; i < tabWidget.getChildCount(); i++) {
RelativeLayout tabLayout = (RelativeLayout) tabWidget.getChildAt(i);
tabLayout.setBackgroundDrawable(someimage);
}
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 :)