自定义视图向下转换不起作用

时间:2017-10-19 13:30:30

标签: android android-custom-view layout-inflater downcast

我有一个自定义视图,CourseRaceButton,它扩展了LinearLayout并将显示在RecyclerView中。使用自定义视图的目的是将状态控件枚举分别嵌入到每个按钮中,以便根据选择的种族或课程来更改颜色等。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="@dimen/courseRace_width"
    android:layout_height="match_parent"
    android:layout_centerInParent="true"
    android:layout_margin="@dimen/courseRace_margin"
    android:background="@drawable/courses_border"
    android:padding="@dimen/courseRace_padding"
    >

<TextView
    android:id="@+id/course_id"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:visibility="gone" />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:weightSum="2">

    <TextView
        android:id="@+id/course_name"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:padding="@dimen/default_padding"
        android:text="Ascot"
        android:textColor="@color/brb_blue">

    </TextView>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal"
        android:weightSum="2">

        <TextView
            android:id="@+id/course_time"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:padding="@dimen/default_padding"
            android:text="11:00"
            android:textColor="@color/brb_blue"/>

        <TextView
            android:id="@+id/course_MTP"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="right"
            android:padding="@dimen/default_padding"
            android:text="MTP 10"
            android:textColor="@color/brb_blue"/>

    </LinearLayout>
</LinearLayout>

这是视图的XML。我已经将包含viewGroup作为LinearLayout(而不是我的CourseRaceButton,因为它导致了通胀问题,因为我不需要在以前的Custom LinearLayout中这样做)。

public class CourseRaceButton extends LinearLayout{

private ButtonStates state;

private TextView title;
private TextView time;
private TextView mtp;

public CourseRaceButton(Context context) {
    super(context);
    init();
}

public CourseRaceButton(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    init();
}

public CourseRaceButton(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
}

public void init(){

    LayoutInflater.from(getContext()).inflate(
            R.layout.course_layout, this);

    title = findViewById(R.id.course_id);
    time = findViewById(R.id.course_time);
    mtp = findViewById(R.id.course_MTP);
    state = ButtonStates.UNSELECTED;

}

这是我的RecyclerView适配器的onBindViewHolder:

@Override
public void onBindViewHolder(final holder holder, final int position) {
    holder.button.getTitle().setText(courses.get(position).name);

    if (!initialised) {
        holder.button.setState(ButtonStates.UNSELECTED);
        previousSelectedCourse = holder.itemView;
        currentCourse=courses.get(position);

        if (position == 0) {
            OnCourseClickListener.onCourseClick(currentCourse);
            holder.button.setState(ButtonStates.SELECTED);
            previousSelectedCourse = holder.itemView;
        }
        initialised = true;
    }

理想情况下,previousSelectedCourse = holder.itemView应该下载到我的CourseRaceButton(更多关于这一点的内容)

这是OnClick:

@Override
    public void onClick(View v) {

        Log.e("TESTING ******"," ON TOUCH " );
        /** Sort out colours as we may have changed button */

        currentCourse = courses.get(this.getAdapterPosition());
        CourseRaceButton b = (CourseRaceButton) v;
        if(b.getState() == ButtonStates.SELECTED){
            return;

现在,如果点击一个按钮,我就会在此行收到错误

CourseRaceButton b = (CourseRaceButton) v;

java.lang.ClassCastException:android.widget.LinearLayout无法强制转换为com.ineda.terminal.CourseRaceButton

My CourseRaceButton扩展了LinearLayout,因此CourseRaceButton是一个LinearLayout,为什么我不能将视图向下转换为CourseRaceButton?我假设v是一个LinearLayout,因为它是在XML中声明的,但是将它更改为CourseRaceButton会给我一个无限的错误循环(因为很明显,inflater正在尝试创建引用自身的Layout)。

如果我无法向下转换LinearLayout,我无法更改其状态枚举以更新其颜色。

可能有一些方法可以解决这个问题,我对其中的任何一个开放

编辑: 这是onCreateViewHolder

public holder onCreateViewHolder(ViewGroup parent, int viewType) {
    View iv = LayoutInflater.from(parent.getContext()).inflate(R.layout.course_layout, parent, false);
    return new holder(iv);
}

根据请求,这是我将course_layout.xml中的第一个LinearLayout更改为CourseRaceButton时获得的无限循环的循环。

at com.ineda.terminal.CourseRaceButton.init(CourseRaceButton.java:41)
at com.ineda.terminal.CourseRaceButton.<init>(CourseRaceButton.java:31)
at java.lang.reflect.Constructor.newInstance0!(Native method) 
at java.lang.reflect.Constructor.newInstance(Constructor.java:430)
at android.view.LayoutInflater.createView(LayoutInflater.java:645)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:787) 
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:727)
at android.view.LayoutInflater.inflate(LayoutInflater.java:495)
- locked <0x05c7192a> (a java.lang.Object[])
at android.view.LayoutInflater.inflate(LayoutInflater.java:426)
at android.view.LayoutInflater.inflate(LayoutInflater.java:377)
at com.ineda.terminal.CourseRaceButton.init(CourseRaceButton.java:41)
at com.ineda.terminal.CourseRaceButton.<init>(CourseRaceButton.java:31)
at java.lang.reflect.Constructor.newInstance0!(Native method)

10-19 15:00:41.792 17508-17508/ineda.com.genericterminal.ineda A/art: 
art/runtime/runtime.cc:422]   at 
java.lang.reflect.Constructor.newInstance(Constructor.java:430)
at android.view.LayoutInflater.createView(LayoutInflater.java:645)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:787)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:727)
at android.view.LayoutInflater.inflate(LayoutInflater.java:495)
- locked <0x05c7192a> (a java.lang.Object[])
at android.view.LayoutInflater.inflate(LayoutInflater.java:426)
at android.view.LayoutInflater.inflate(LayoutInflater.java:377)

1 个答案:

答案 0 :(得分:1)

创建ViewHolder时,您可以通过以下方式将其从XML中扩充:

Polyline

显然,Adapter然后对您的自定义视图一无所知,因为ViewHolder是以root身份使用常规LinearLayout创建的。

因此,根据您的需要,您需要通过手动实例化将自定义View的实例传递给ViewHolder:

public holder onCreateViewHolder(ViewGroup parent, int viewType) {
    View iv = 
    LayoutInflater.from(parent.getContext()).inflate(R.layout.course_layout, 
    parent, false);
    return new holder(iv);
}

或者您需要将自定义视图用作XML的根目录。但是,您需要修复逻辑中的缺陷 - 不要通过声明自定义视图的相同布局来扩充自定义视图。这就是为什么你得到这种无限循环的例外。