Android 初始化滚动条未定义? 背景
我使用它作为它的一个类(从ViewGroup扩展而来),在“PLA_AbsListView.java”中,在CTOR内部,有以下几行:Android 初始化滚动条未定义? 背景,android,android-5.0-lollipop,Android,Android 5.0 Lollipop,我使用它作为它的一个类(从ViewGroup扩展而来),在“PLA_AbsListView.java”中,在CTOR内部,有以下几行: final TypedArray a = context.obtainStyledAttributes(R.styleable.View); initializeScrollbars(a); a.recycle(); 最近,我更新了Android的SDK和ADT,以支持新的Android版本(棒棒糖-API21) 问题 自从我更新了所有
final TypedArray a = context.obtainStyledAttributes(R.styleable.View);
initializeScrollbars(a);
a.recycle();
最近,我更新了Android的SDK和ADT,以支持新的Android版本(棒棒糖-API21)
问题
自从我更新了所有内容后,我一直遇到以下错误:
类型PLA_AbsListView的方法initializeScrollbars(TypedArray)未定义
我试过的
我尝试将API设置为低于21,但没有帮助
我还试图找出这个函数的声明位置。它应该是“View.java”中的一个受保护函数,但由于某些原因,我无法在中看到它
问题
怎么可能呢
我怎样才能修好它
有可能是文档中的错误吗
以前,当从android-21的
View.java
中瞄准Kitkat…时,它起到了作用
/**
* ...
*
* @removed
*/
protected void initializeScrollbars(TypedArray a) {
// 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.
TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
initializeScrollbarsInternal(arr);
// We ignored the method parameter. Recycle the one we actually did use.
arr.recycle();
}
/**
* ...
*
* @hide
*/
protected void initializeScrollbarsInternal(TypedArray a) {
您看不到它,因为该方法是用@removed
注释的initializeScrollbarsInternal()
也不能使用,因为它是用@hide
注释的。
从评论来看,使用这种方法不安全,你应该明确地向lib的作者报告。正如@biegleux在他的回答中提到的,
initializeScrollbars()
现在在API 21源代码中被注释为@removed
。以下是API 21中的方法源:
protected void initializeScrollbars(TypedArray a) {
// 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.
TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
initializeScrollbarsInternal(arr);
// We ignored the method parameter. Recycle the one we actually did use.
arr.recycle();
}
根据方法中的注释,API 21之前的问题似乎是传入TypedArray
不安全,但现在它不再使用传入的TypedArray
。因此,似乎应该使用@Deprecated
而不是@removed
对该方法进行注释,并且应该有一个新版本的该方法,当我们需要从以编程方式创建的自定义视图中初始化滚动条时,不需要调用任何参数
在解决此问题之前,有两种方法可以解决此问题:
1) 使用android:scrollbars
属性集从xml扩展自定义视图。这是最安全的方法,应该适用于所有过去和将来的平台版本。例如:
创建xml布局文件(my\u custom\u view.xml
):
2) 使用反射在自定义视图的构造函数中调用initializeScrollbars()
。如果方法initializeScrollbars()
实际被删除或重命名,则在将来的API版本中,此操作可能会失败。例如:
在自定义视图中(例如,MyCustomView.java
):
+1.我将sdk改回API 19进行检查,并在那里定义。它已被删除,没有解释。奇怪。@rockgecko所以也许我应该报告这件事?@rockgecko好的,我已经在这里报告过了:这样的东西怎么能被移除?如果删除该调用,它在以前的版本中如何工作?你会因为它而对以前的版本使用反射吗?如果调用同一API不是一件安全的事情,那么库的早期版本如何能够在同一API上工作?如果它不安全,为什么不删除里面的代码呢?我只是不明白…问题是lib在获取保存属性值的
TypedArray
时使用R.styleable.View
。相反,它应该使用com.android.internal.R.styleable.View
,但它是内部的,不能从SDK访问。我能猜到的问题是什么,可能是它导致了一些泄漏或不正确的样式。我建议您从库中删除initializeScrollbars()
,并通过定义R.styleable.View\u scrollbars
attr将其放在View
类中,该属性不是内部的。查看View.java的源代码,我已经删除了它,但我希望它不会在旧版本和新版本的Android上造成任何问题。你是说它已经通过CTOR初始化了?如果是这样的话,以前版本的Android也是这样吗?我想知道为什么会添加它……不,它不是通过ctor初始化的,但是如果您能够使用另外两个ctor中的一个,那么如果您将滚动条设置为垂直,它应该可以。或者您可以检查它是否可以帮助您,它直接继承自AbsListView
,而不创建自己的实现。
<com.example.MyCustomView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="horizontal|vertical"/>
MyCustomView view = (MyCustomView) LayoutInflater.from(context).inflate(R.layout.my_custom_view, container, false);
public MyCustomView(Context context) {
super(context);
// Need to manually call initializedScrollbars() if instantiating view programmatically
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();
}