以正确的方式以编程方式实例化自定义视图
Instantiate custom view programmatically the right way
我有一个名为 EventItemView
的自定义视图,我在 和 XML 文件以及自定义适配器(扩展 RecyclerView.Adapter
并用在 RecyclerView
) 中。我的问题是它在我的 RecyclerView
中的出现很奇怪,但在我的 XML 文件中却没有:
- 使用XML
声明
- 在我的适配器中动态实例化
而且我相信这是由于我在我的适配器中实例化视图的方式,通过执行 new EventItemView(context)
而不是向它传递额外的参数 AttributeSet, int, int
可能需要它来呈现 XML版本。问题是我不知道如何将它们放入我的适配器中。
这是自定义视图声明:
EventItemView.java
public class EventItemView extends FrameLayout {
public EventItemView(Context context) {
this(context, null);
}
public EventItemView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public EventItemView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr, 0);
init(context, attrs, defStyleAttr, 0);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public EventItemView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs, defStyleAttr, defStyleRes);
}
protected void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
eventItem = new EventItem();
inflate(context, R.layout.view_event_item, this);
ButterKnife.bind(this);
TypedArray values = context.getTheme().obtainStyledAttributes(attrs, R.styleable.EventItemView, defStyleAttr, defStyleRes);
try {
setSubtitle(values.getString(R.styleable.EventItemView_subtitle));
...
}
finally {
values.recycle();
}
}
}
layout/view_event_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/selector_item_event"
android:clickable="true"
android:gravity="center"
android:layout_height="72dp"
android:layout_width="match_parent"
android:orientation="horizontal"
android:padding="16dp">
...
</LinearLayout>
然后在 1) activity.xml 文件中使用此视图:
<com.app.package.view.EventItemView
android:id="@+id/current_event_view"
android:layout_height="wrap_content"
android:layout_width="match_parent" />
和 2) 在 Adapter.java 中:
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
EventItemView itemView = new EventItemView(context);
return new ViewHolder(itemView);
}
如何使用相关的 attrs
、defStyleAttr
和 defStyleRes
构造函数参数正确实例化我的自定义视图?或者,也许视图出于完全不同的原因以奇怪的方式表现?
您需要先调用 measure()
,然后再调用 layout()
。
实例化的自定义视图不知道它需要膨胀到的大小,因此您需要通过这些调用传递它。
通过更改解决了我的问题
public class EventItemView extends FrameLayout
至
public class EventItemView extends RelativeLayout
我只是不明白为什么。
我有一个名为 EventItemView
的自定义视图,我在 和 XML 文件以及自定义适配器(扩展 RecyclerView.Adapter
并用在 RecyclerView
) 中。我的问题是它在我的 RecyclerView
中的出现很奇怪,但在我的 XML 文件中却没有:
- 使用XML 声明
- 在我的适配器中动态实例化
而且我相信这是由于我在我的适配器中实例化视图的方式,通过执行 new EventItemView(context)
而不是向它传递额外的参数 AttributeSet, int, int
可能需要它来呈现 XML版本。问题是我不知道如何将它们放入我的适配器中。
这是自定义视图声明:
EventItemView.java
public class EventItemView extends FrameLayout {
public EventItemView(Context context) {
this(context, null);
}
public EventItemView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public EventItemView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr, 0);
init(context, attrs, defStyleAttr, 0);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public EventItemView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs, defStyleAttr, defStyleRes);
}
protected void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
eventItem = new EventItem();
inflate(context, R.layout.view_event_item, this);
ButterKnife.bind(this);
TypedArray values = context.getTheme().obtainStyledAttributes(attrs, R.styleable.EventItemView, defStyleAttr, defStyleRes);
try {
setSubtitle(values.getString(R.styleable.EventItemView_subtitle));
...
}
finally {
values.recycle();
}
}
}
layout/view_event_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/selector_item_event"
android:clickable="true"
android:gravity="center"
android:layout_height="72dp"
android:layout_width="match_parent"
android:orientation="horizontal"
android:padding="16dp">
...
</LinearLayout>
然后在 1) activity.xml 文件中使用此视图:
<com.app.package.view.EventItemView
android:id="@+id/current_event_view"
android:layout_height="wrap_content"
android:layout_width="match_parent" />
和 2) 在 Adapter.java 中:
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
EventItemView itemView = new EventItemView(context);
return new ViewHolder(itemView);
}
如何使用相关的 attrs
、defStyleAttr
和 defStyleRes
构造函数参数正确实例化我的自定义视图?或者,也许视图出于完全不同的原因以奇怪的方式表现?
您需要先调用 measure()
,然后再调用 layout()
。
实例化的自定义视图不知道它需要膨胀到的大小,因此您需要通过这些调用传递它。
通过更改解决了我的问题
public class EventItemView extends FrameLayout
至
public class EventItemView extends RelativeLayout
我只是不明白为什么。