我想编写一个自定义视图,需要一些带有特定id的按钮(能够通过id找到),就像在ListActivity中一样,android.R.id.list必须存在,我该怎么办与我自己的自定义ID相同吗?
我计划在Android lib中重用这个视图用于几个用例,但是所有这些视图都必须声明一些具有特定id的特定视图,以便我可以在lib代码中通过id找到它并对其进行操作以供以后用于使用应用...
答案 0 :(得分:2)
只需执行ListActivity所做的工作。
检查自定义视图中的ID,如果布局中不存在则抛出异常。
来自ListActivity的片段资料来源:
@Override
public void onContentChanged() {
super.onContentChanged();
View emptyView = findViewById(com.android.internal.R.id.empty);
mList = (ListView)findViewById(com.android.internal.R.id.list);
if (mList == null) {
throw new RuntimeException(
"Your content must have a ListView whose id attribute is " +
"'android.R.id.list'");
}
答案 1 :(得分:2)
最好的方法是以灵活的方式使用自定义属性。它允许任何id成为必需的id,但它也使用dev工具强制使用有效的id。
声明您的自定义视图可以在attrs.xml文件中使用自定义属性进行样式化,如下所示:
<resources>
<declare-styleable name="MyView">
<attr name="required_view_id" format="integer" />
</declare-styleable>
</resources>
然后,您可以从下面的布局文件中引用该属性。特别注意定义“app”命名空间的标题。您可以为自定义属性命名空间使用任何名称,但在以后定义视图时必须声明它以使用任何自定义属性。请注意MyView上的自定义属性。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:id="@+id/the_id_of_the_required_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.full.package.to.MyView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:required_view_id="@id/the_id_of_the_required_view" />
</LinearLayout>
现在,您需要确保自定义视图类中存在此视图。您可以要求通过覆盖某些构造函数来设置自定义属性。您还需要在某些时候实际验证所需视图的存在。这是一个粗略的想法:
public class MyView extends View {
private int mRequiredId;
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
checkForRequiredViewAttr(context, attrs);
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
checkForRequiredViewAttr(context, attrs);
}
// Verify that the required id attribute was set
private void checkForRequiredViewAttr(Context context, AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.MyView, 0, 0);
mRequiredId = a.getResourceId(R.styleable.MyView_required_view_id, -1);
a.recycle();
if (mRequiredId == -1) {
throw new RuntimeException("No required view id attribute was set");
}
}
// This allows the custom view to be programmatically instantiated, so long as
// the required id is manually set before adding it to a layout
public void setRequiredId(int id) {
mRequiredId = id;
}
// Check for the existence of a view with the required id
@Override
protected void onAttachedToWindow() {
View root = getRootView();
View requiredView = root.findViewById(mRequiredId);
if (requiredView == null) {
throw new RuntimeException(
String.format("Cannot find view in layout with id of %s", mRequiredId));
}
super.onAttachedToWindow();
}
}
使用onAttachedToWindow检查所需的视图可能不够用于您的目的。例如,它不会阻止删除所需的视图。在布局中查找视图并不是一种廉价的操作,尤其是对于复杂的布局,因此您不应该经常检查它。