0

I want to add scrollbars to my custom view programmatically. Before Lollipop, this was done in the constructor like so:

setHorizontalScrollBarEnabled(true);
setVerticalScrollBarEnabled(true);

TypedArray a = context.obtainStyledAttributes(R.styleable.View);
initializeScrollbars(a);
a.recycle();

(see here)

Now with the introduction of Lollipop, Google made the initializeScrollbars() API private so it's no longer available (see here)

So people have suggested to just manually import initializeScrollbars() and call it, like so:

final TypedArray a = context.getTheme().obtainStyledAttributes(new int[0]);
try {
    // initializeScrollbars(TypedArray)
    Method initializeScrollbars = android.view.View.class.getDeclaredMethod("initializeScrollbars", TypedArray.class);
    initializeScrollbars.invoke(this, a);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
    e.printStackTrace();
}
a.recycle();

This does the trick but of course it's a hack.

So does this mean that more than 4 years after the introduction of Lollipop and the removal of initializeScrollbars() it is still impossible to programmatically add scrollbars to a custom view and that the only safe way to do that is to inflate an XML or is there a clean solution to do this in the meanwhile?

It's hard to imagine for Google to remove initializeScrollbars() without providing an alternative way to do what it does... especially since it has been 4 years now and adding scrollbars to a custom view looks like a rather common task so I'm really puzzled why this is apparently so complicated to achieve programmatically.

aminography
  • 21,986
  • 13
  • 70
  • 74
Andreas
  • 9,245
  • 9
  • 49
  • 97
  • `It's hard to imagine for Google to remove initializeScrollbars() without providing an alternative way to do what it does..` — you obviously don't know Google. – TheWanderer Oct 21 '18 at 14:04
  • No, I don't :D But seriously, it's such a common task and the only way to do it is to inflate XML? I'm still reluctant to believe this. – Andreas Oct 21 '18 at 14:06
  • `initializeScrollbars()` has had protected access since at least JellyBean. You should have no trouble calling it from your View subclass. You just can't call it from other classes. – TheWanderer Oct 21 '18 at 14:09
  • Oh sorry I see. It has the removed tag, meaning the SDK won't show it. However, there is a reason for why it's been removed: `It's not safe to use this method from apps. The parameter 'a' must have been obtained using the View filter array which is not available to the SDK. As such, internal framework usage now uses initializeScrollbarsInternal and we grab a default TypedArray with the right filter instead here.` – TheWanderer Oct 21 '18 at 14:13
  • Yeah, there is a reason, but there is no replacement AFAICS. That's what my post is about.... they just nuked it without providing a replacement :( – Andreas Oct 21 '18 at 14:14
  • I can show you many other examples of Google removing features without replacements. It's something you need to get used to. You also should be using `initializeScrollbarsInternal` in your reflection, since `initializeScrollbars` doesn't have any function. – TheWanderer Oct 21 '18 at 14:15
  • Why? I've just checked the Android source code and `initializeScrollbars` seems to call `initializeScrollbarsInternal`, doesn't it? – Andreas Oct 21 '18 at 14:22
  • It does, but with the default View TypedArray. It ignores the one you pass. – TheWanderer Oct 21 '18 at 14:22
  • Is that of any significance? I just want to have some scrollbars, I don't care what they look like ;) – Andreas Oct 21 '18 at 14:24
  • Actually, I don't think you really need to call `initializeScrollbars()`. Have you tried without it? – TheWanderer Oct 21 '18 at 14:28
  • Yes, I've just tried it and it doesn't work. When leaving out the call to `initializeScrollbars()` no scroll bars show up. It is necessary. At least on Android 7, which is my test system, that is. – Andreas Oct 21 '18 at 14:32
  • Then I guess you'll need to stick with reflection. – TheWanderer Oct 21 '18 at 14:35
  • I was afraid you'd say that ;) – Andreas Oct 21 '18 at 14:36
  • does the `ScrollView` created programmatically show the scrollbars? if so, did they use `initializeScrollbars()` method in `ScrollView.java`? – pskink Oct 21 '18 at 15:43
  • No, they don't use `initializeScrollbars()` at all in `ScrollView.java`. They also don't use `setHorizontalScrollbarEnabled()` and `setVerticalScrollbarEnabled()`. – Andreas Oct 24 '18 at 14:09

0 Answers0