Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to shrink SwitchCompat width?

I want to reduce my Switch's width. The current solution in How to change the size of a Switch Widget and How to change Width of Android's Switch track? is not solving my problem. android:switchMinWidth just defined the minWidth, but I want it to be smaller than 2 x thumbWidth size.

I dig into the SwitchCompat class' onMeasure() function. The way the width is defined is as below.

    // Adjust left and right padding to ensure there's enough room for the
    // thumb's padding (when present).
    int paddingLeft = padding.left;
    int paddingRight = padding.right;
    if (mThumbDrawable != null) {
        final Rect inset = DrawableUtils.getOpticalBounds(mThumbDrawable);
        paddingLeft = Math.max(paddingLeft, inset.left);
        paddingRight = Math.max(paddingRight, inset.right);
    }

    final int switchWidth = Math.max(mSwitchMinWidth,
            2 * mThumbWidth + paddingLeft + paddingRight);
    final int switchHeight = Math.max(trackHeight, thumbHeight);
    mSwitchWidth = switchWidth;
    mSwitchHeight = switchHeight;

I was considering using negative padding, but then there's this line paddingLeft = Math.max(paddingLeft, inset.left);. I'm not sure how to set the inset to my thumb drawable that has negative value (I don't know what inset or OpticalBounds is. Maybe this should be another stackoverflow question ).

Anyone has idea how I could shrink the width of my SwitchCompat?

Update I have filed a request to google on this https://code.google.com/p/android/issues/detail?id=227184&thanks=227184&ts=1478485498

like image 591
Elye Avatar asked Nov 09 '22 06:11

Elye


1 Answers

The current approach I could workaround the challenge is using reflection to force set the mSwitchWidth variable right after the onMeasure(...) function is called.

public class SwitchCustomWidth extends SwitchCompat {

    //... the needing constructors goes here...    

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        try {
            Field switchWidth = SwitchCompat.class.getDeclaredField("mSwitchWidth");
            switchWidth.setAccessible(true);

            // Using 120 below as example width to set
            // We could use attr to pass in the desire width
            switchWidth.setInt(this, 120);

        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

This is not ideal. I hope to have someone else contribute a better answer, without needing reflection (or copy entire class over to modify the class, or rewriting a custom Switch just because of the width issue).

If there's no solution out there, then this would serve best for now to help others facing the same challenge.

like image 151
Elye Avatar answered Nov 15 '22 06:11

Elye