I want to remove the padding around the icon on the left in the standard android 4.0+ action bar. I'm setting the icon with:
getActionBar().setIcon(getResources().getDrawable(R.drawable.ic_action_myapp));
And I would like the icon to fill vertically the space, touching both top and bottom, similar to what soundcloud app does:
Digging into AOSP sources, it seems the code involved is in com.android.internal.widget.ActionBarView.java
. In particular the relevant part is the onLayout()
method of the inner class ActionBarView$HomeView
, partially reported below (lines 1433-1478):
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
...
final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
final int iconHeight = mIconView.getMeasuredHeight();
final int iconWidth = mIconView.getMeasuredWidth();
final int hCenter = (r - l) / 2;
final int iconTop = Math.max(iconLp.topMargin, vCenter - iconHeight / 2);
final int iconBottom = iconTop + iconHeight;
final int iconLeft;
final int iconRight;
int marginStart = iconLp.getMarginStart();
final int delta = Math.max(marginStart, hCenter - iconWidth / 2);
if (isLayoutRtl) {
iconRight = width - upOffset - delta;
iconLeft = iconRight - iconWidth;
} else {
iconLeft = upOffset + delta;
iconRight = iconLeft + iconWidth;
}
mIconView.layout(iconLeft, iconTop, iconRight, iconBottom);
}
the same widget use this layout, defined in res/layout/action_bar_home.xml
:
<view xmlns:android="http://schemas.android.com/apk/res/android"
class="com.android.internal.widget.ActionBarView$HomeView"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<ImageView android:id="@android:id/up"
android:src="?android:attr/homeAsUpIndicator"
android:layout_gravity="center_vertical|start"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="-8dip" />
<ImageView android:id="@android:id/home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dip"
android:layout_marginTop="@android:dimen/action_bar_icon_vertical_padding"
android:layout_marginBottom="@android:dimen/action_bar_icon_vertical_padding"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="fitCenter" />
</view>
According to sources the icon is shown in the Imageview
with id=android.R.id.home
. The onLayout()
method reported above takes account of the ImageView
margins defined in the layout, which can't be set via theme/style override because they use the value @android:dimen/action_bar_icon_vertical_padding
.
All you can do is to get rid of those values at runtime, and set them according your needs:
simply retrieve the ImageView
and set its top and bottom margins to 0
. Something like this:
ImageView icon = (ImageView) findViewById(android.R.id.home);
FrameLayout.LayoutParams iconLp = (FrameLayout.LayoutParams) icon.getLayoutParams();
iconLp.topMargin = iconLp.bottomMargin = 0;
icon.setLayoutParams( iconLp );
EDIT: I've just realized I didn't cover how to get rid of left padding. Solution below.
Left padding on actionbar is affected by the Navigating Up behavior of actionbar icon. When that is disabled (via ActionBar.setDisplayHomeAsUpEnabled(false)
) the left/up indicator is gone, but a left padding is used as well. A simple solution:
- enable the actionbar up navigation using
ActionBar.setDisplayHomeAsUpEnabled(true)
in order to consider the indicator view in the layout process
- force the drawable used as up indicator in your
res/values-v14/styles.xml
to null
eg:
<style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<!-- API 14 theme customizations can go here. -->
<item name="android:homeAsUpIndicator">@null</item>
</style>
I found an other resolution (reference appcompat-v7 ) that change the toolbarStyle ,following code:
<item name="toolbarStyle">@style/Widget.Toolbar</item>
<style name="Widget.Toolbar" parent="@style/Widget.AppCompat.Toolbar">
<item name="contentInsetStart">0dp</item>
</style>
use custom layout for ActionBar
public class TestActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ActionBar actionBar = getActionBar();
actionBar.setCustomView(R.layout.actionbar_custom_view_home);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setDisplayUseLogoEnabled(false);
actionBar.setDisplayShowHomeEnabled(false);
setContentView(R.layout.main);
}
public void Click(View v) {
if (v.getId() == R.id.imageIcon) {
Log.e("click on--> ", "Action icon");
}
}
}
actionbar_custom_view_home.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center" >
<ImageView
android:id="@+id/imageIcon"
android:onClick="Click"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="@drawable/ic_launcher" />
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Large Icon With Title"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
Enhanced parrzhang reply in remove padding around action bar left icon on Android 4.0+
private void adjustHomeButtonLayout(){
ImageView view = (ImageView)findViewById(android.R.id.home);
if(view.getParent() instanceof ViewGroup){
ViewGroup viewGroup = (ViewGroup)view.getParent();
View upView = viewGroup.getChildAt(0);
if(upView != null && upView.getLayoutParams() instanceof FrameLayout.LayoutParams){
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) upView.getLayoutParams();
layoutParams.width = 20;// **can give your own width**
upView.setLayoutParams(layoutParams);
}
}
}
To set the height of ActionBar you can create new Theme like this one:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.BarSize" parent="Theme.Sherlock.Light.DarkActionBar">
<item name="actionBarSize">48dip</item>
<item name="android:actionBarSize">48dip</item>
</style>
</resources>
and set this Theme to your Activity:
android:theme="@style/Theme.BarSize"
Now, set the height of the icons to "match_parent"
.
That would remove the top and bottom padding.
Now, the arrow at the left is inbuilt into the framework, so you have two options for a workaround:
Use ActionBarSherlock. It uses it's own drwables and resources, so you can modify the arrow icon to an emty png, so that your up icon would move to extreme left.
The up/back icon arises from:
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
}
}
So, instead of using this option for up button, you can make another actionbar option, which has an intent for the previous activity, and then place that icon on your action bar.
It will be a bigger workaround though.
Hope that helps.. :)
you can find homeview in actionbarview define like this:
<view xmlns:android="http://schemas.android.com/apk/res/android"
class="com.android.internal.widget.ActionBarView$HomeView"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<ImageView android:id="@android:id/up"
android:src="?android:attr/homeAsUpIndicator"
android:layout_gravity="center_vertical|start"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="-8dip" />
<ImageView android:id="@android:id/home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dip"
android:layout_marginTop="@android:dimen/action_bar_icon_vertical_padding"
android:layout_marginBottom="@android:dimen/action_bar_icon_vertical_padding"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="fitCenter" />
but you cannot get upView by findViewById(android.R.id.up)
.
so you can get homeView and get its parent view ,set upview width 0
ImageView view = (ImageView)findViewById(android.R.id.home);
if(view.getParent() instanceof ViewGroup){
ViewGroup viewGroup = (ViewGroup)view.getParent();
View upView = viewGroup.getChildAt(0);
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) upView.getLayoutParams();
layoutParams.width = 0;
upView.setLayoutParams(layoutParams);
}