Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Try my hack, seems to work at least on 2.2 and above.</p> <pre><code>import java.lang.reflect.Field; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.widget.ListView; /** * This class fixes the lack of setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_LEFT) before API level 11 * @author Genadz Batsyan */ public class ListViewWithLeftScrollBar extends ListView { private static final String LOG_TAG = ListViewWithLeftScrollBar.class.getSimpleName(); private static final boolean DEBUG = true; private boolean patchInvalidate; public ListViewWithLeftScrollBar(Context context) { super(context); moveVerticalScrollbarToTheLeft(); } public ListViewWithLeftScrollBar(Context context, AttributeSet attrs) { super(context, attrs); moveVerticalScrollbarToTheLeft(); } public ListViewWithLeftScrollBar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); moveVerticalScrollbarToTheLeft(); } @Override public void invalidate(Rect r) { invalidate(r.left, r.top, r.right, r.bottom); } @Override public void invalidate(int left, int top, int right, int bottom) { int width = right - left; if (DEBUG) log("invalidate original w:"+ getWidth() +" h:"+ getHeight()+" rect:"+left+", "+top+", "+right+", "+bottom); if (patchInvalidate &amp;&amp; right == getWidth() &amp;&amp; top == 0 &amp;&amp; bottom == getHeight() &amp;&amp; width &lt; 30) { // The above condition should ensure that ListView is VERY likely to be invalidating the scrollbar. // In fact ListView appears to not invalidate anything except the scrollbar, ever. left = 0; right = left + width; if (DEBUG) log("invalidate patched w:"+ getWidth() +" h:"+ getHeight()+" rect:"+left+", "+top+", "+right+", "+bottom); } super.invalidate(left, top, right, bottom); } private void moveVerticalScrollbarToTheLeft() { try { if (DEBUG) log("moveVerticalScrollbarToTheLeft: Trying API Level &gt;=11"); tryApiLevel11(); if (DEBUG) log("moveVerticalScrollbarToTheLeft: API Level &gt;=11 success"); } catch (Throwable t1) { if (DEBUG) { log("moveVerticalScrollbarToTheLeft: API Level &gt;=11 FAILED"); t1.printStackTrace(); } try { if (DEBUG) log("moveVerticalScrollbarToTheLeft: Trying hack for API Level &lt;11"); tryApiLevelPre11(); patchInvalidate = true; if (DEBUG) log("moveVerticalScrollbarToTheLeft: API Level &lt;11 hack success"); } catch (Throwable t2) { if (DEBUG) { log("moveVerticalScrollbarToTheLeft: API Level &lt;11 hack FAILED"); t2.printStackTrace(); } } } } @SuppressLint("NewApi") private void tryApiLevel11() { setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_LEFT); } private void tryApiLevelPre11() throws Exception { Class&lt;?&gt; viewClass = View.class; Field scrollCacheField = viewClass.getDeclaredField("mScrollCache"); scrollCacheField.setAccessible(true); Object scrollCache = scrollCacheField.get(this); if (DEBUG) log("scrollCache: "+ scrollCache); Field scrollBarField = scrollCache.getClass().getDeclaredField("scrollBar"); scrollBarField.setAccessible(true); Object scrollBar = scrollBarField.get(scrollCache); if (DEBUG) log("scrollBar: "+ scrollBar); Field verticalThumbField = scrollBar.getClass().getDeclaredField("mVerticalThumb"); verticalThumbField.setAccessible(true); Object verticalThumb = verticalThumbField.get(scrollBar); if (DEBUG) log("verticalThumb: "+ verticalThumb); Drawable verticalThumbDrawable = (Drawable) verticalThumb; Drawable replacementVerticalThumbDrawable = new LayerDrawable(new Drawable[]{ verticalThumbDrawable }) { @Override public void setBounds(int left, int top, int right, int bottom) { if (DEBUG) log("setBounds original: "+left+", "+top+", "+right+", "+bottom); int width = right - left; left = 0; right = left + width; if (DEBUG) log("setBounds patched: "+left+", "+top+", "+right+", "+bottom); super.setBounds(left, top, right, bottom); } }; verticalThumbField.set(scrollBar, replacementVerticalThumbDrawable); } private static void log(String msg) { Log.d(LOG_TAG, msg); } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload