2

I have an overflow menu with a checkable menu item. I would like to align the CheckBox all the way to the end, but I don't know how this can be done.

My menu is defined like so:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:icon="@drawable/ic_baseline_more_vert_24"
        android:title=""
        app:showAsAction="always">
        <menu>
            <item
                android:id="@+id/desktop_site"
                android:checkable="true"
                android:checked="false"
                android:icon="@drawable/ic_baseline_desktop_windows_24"
                android:title="Desktop site"
                app:showAsAction="never" />
        </menu>
    </item>
</menu>

Overflow menu

Zain
  • 37,492
  • 7
  • 60
  • 84
shko
  • 64
  • 2
  • 20

3 Answers3

2

You can create a custom style to the CheckBox and adjust the end padding with a negative value:

<style name="checkbox_style" parent="android:style/Widget.Holo.Light.CompoundButton.CheckBox">
    <item name="android:paddingRight">-7dp</item>
</style>

And apply it to your app's theme:

<item name="checkboxStyle">@style/checkbox_style</item>

enter image description here

Note: By default there should be some margin surrounds a menu item; so you can't send the checkBox to the far end, as its right edge will cut:

When using -8dp:

enter image description here

So, you need to be careful in handling this.

UPDATE

but it affects all the CheckBoxes in my app

This requires to reverse this padding in all of CheckBoxes in your layouts; and there are options for this:

  • First option: add android:paddingRight="7dp" / android:paddingEnd="7dp" to all the CheckBoxes.
  • Second option: Create a custom CheckBox class and add this padding to its constructors; and use this customized CheckBox instead of the default CheckBox:
public class MyCheckBox extends AppCompatCheckBox {

    public MyCheckBox(Context context) {
        super(context);
        init();
    }

    public MyCheckBox(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        int px = (int) TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP,
                7f, // dp value
                getResources().getDisplayMetrics()
        );
        setPadding(0, 0, px, 0);
    }

    public MyCheckBox(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }


}

And to use it:

<!-- Add the full path of the customized CheckBox -->
<com.example.android......MyCheckBox   
    android:id="@+id/checkbox2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
/>

Hint: If you target API-17+, then use android:paddingEnd instead android:paddingRight

Zain
  • 37,492
  • 7
  • 60
  • 84
  • Also have a look at this [question](https://stackoverflow.com/questions/17154557/how-do-can-i-remove-padding-from-menuitem-in-actionbar) – Zain Oct 23 '21 at 00:31
  • This works, but it affects all the CheckBoxes in my app – shko Oct 23 '21 at 07:41
  • @shko Absolutely right; please have a look at the updated answer; hopefully it works now. – Zain Oct 23 '21 at 10:28
  • 1
    Nice, this is probably the way to do it. Too bad these things can't be styled through `Widget.AppCompat.PopupMenu.Overflow` directly – shko Oct 23 '21 at 11:19
  • @shko Unfortunately there is no direct way as this is special type of checkable; even trying to inflate that using ActionView didn't work; if that solved your problem; thanks to accept the answer. – Zain Oct 25 '21 at 18:37
  • 1
    I accepted the answer and gave you the bounty now. Thanks for the help – shko Oct 26 '21 at 13:10
0

You can use a custom PopupWindow. This allows you to completely customize it. First create a XML file of your Popup. Using wrap_content at the main layout is very important to shrink the Popup to its size.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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:layout_width="wrap_content"
    android:layout_height="wrap_content"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:background="#000000"
        android:padding="5dp"
        android:gravity="center_vertical">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_baseline_desktop_mac_24"
            app:tint="#FFFFFF"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Desktop site"
            android:textColor="#FFFFFF"
            android:layout_marginLeft="10dp"/>

        <CheckBox
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:buttonTint="#FFFFFF"
            android:minWidth="0dp"
            android:minHeight="0dp"
            android:layout_marginLeft="30dp"/>

    </LinearLayout>

</LinearLayout>

enter image description here

Then show the dialog by calling this function. (I copied this code from one of my projects, but I can remember I got it from SO).

private void showPopup(Context context, Point p) {
    LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View layout = layoutInflater.inflate(R.layout.your_popup_xml, null);
    
    PopupWindow changeStatusPopUp = new PopupWindow(context);
    changeStatusPopUp.setContentView(layout);
    changeStatusPopUp.setWidth(LinearLayout.LayoutParams.WRAP_CONTENT);
    changeStatusPopUp.setHeight(LinearLayout.LayoutParams.WRAP_CONTENT);
    changeStatusPopUp.setAnimationStyle(android.R.style.Animation_Dialog);

    int OFFSET_X = -300; //Adjust position of the Popup
    int OFFSET_Y = 50;   //Adjust position of the Popup
        
    changeStatusPopUp.setOutsideTouchable(true);
    changeStatusPopUp.setFocusable(true);
    changeStatusPopUp.setBackgroundDrawable(new BitmapDrawable());
    changeStatusPopUp.showAtLocation(layout, Gravity.NO_GRAVITY, p.x + OFFSET_X, p.y + OFFSET_Y);
}

If you want to catch Click Events, you just need to set an id to the LinearLayout and use it with the view in Java (LinearLayout ll = view.findViewById(R.id.yourId);).

Call the void by:

int[] location = new int[2];
view.getLocationOnScreen(location);
Point point = new Point();
point.x = location[0];
point.y = location[1];
showStatusPopup(context, point);
Jakob
  • 1,858
  • 2
  • 15
  • 26
  • What is p.x and p.y? The PopupWindow is laid out behind my BottomSheet, all the way to the left – shko Oct 23 '21 at 08:10
  • Sorry, I forgot a piece of code. Check my edited answer. I also added the parameter Point p to the void. – Jakob Oct 23 '21 at 12:25
0

When using MaterialComponents some of the padding is from the checkbox itself. This can be removed by setting android:minWidth to 0. The remaining padding is symmetrical and looks good.

Like the accepted solution, create a style:

<style name="checkbox_style" parent="@style/Widget.MaterialComponents.CompoundButton.CheckBox">
    <item name="minWidth">0dp</item>
</style>

And apply it to your app's theme:

<item name="checkboxStyle">@style/checkbox_style</item>
repkap11
  • 757
  • 7
  • 9