我想要编写一个自定义视图,它需要一个带有特定id的按钮才能出现(为了能够被id找到),就像在ListActivity android.R.id.list中必须存在一样,我如何对我自己的自定义id做同样的处理?
我计划在Android中重用这个视图,用于几个用例,但是所有这些用例都必须用特定的id声明一些特定的视图,这样我就可以在lib代码中通过id找到它,并对它进行操作,以便以后在使用应用程序时使用.
发布于 2013-12-18 10:17:41
就像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'");
}
发布于 2013-12-18 12:16:48
最好的方法是灵活地使用自定义属性。它允许任何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检查所需的视图对您来说可能不够好。例如,它不会阻止移除所需的视图。在布局中查找视图并不是一种廉价的操作,特别是对于复杂的布局,因此您不应该经常检查它。
https://stackoverflow.com/questions/20665297
复制相似问题