RelativeLayout无法强制转换为我的自定义列表视图

问题描述 投票:0回答:2

所以我编写了一个自定义列表视图和适配器,以在列表视图中显示我自己的自定义项目行。我有一个功能列表视图,其功能是在选择模式之间切换,并通过列表视图行xml文件中的自定义相对布局来检查列表行项目。现在我正在尝试添加拖放功能,以使用目标代码为android v3.0及更高版本来访问列表视图项。我在这个网站上遇到了这个post,用于拖放的优秀实现,现在我将它添加到我的项目中。 Github source here

当我编译我的项目时,我收到了一个强制转换异常错误,如我的帖子标题中所述,我遇到了麻烦。如果我的自定义相对布局实现可检查,或者拖放的自定义列表视图等,我无法解决。这是我的日志输出

08-02 09:53:37.065: W/dalvikvm(16119): threadid=1: thread exiting with uncaught exception (group=0x40c6f1f8)
08-02 09:53:37.090: E/AndroidRuntime(16119): FATAL EXCEPTION: main
08-02 09:53:37.090: E/AndroidRuntime(16119): java.lang.ClassCastException: android.widget.RelativeLayout cannot be cast to au.drp.mylistview.draganddrop.DragSortListView
08-02 09:53:37.090: E/AndroidRuntime(16119):    at au.drp.mylistview.MyListViewAdapter.getView(MyListViewAdapter.java:62)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at au.drp.mylistview.draganddrop.DragSortListView$AdapterWrapper.getView(DragSortListView.java:270)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.widget.AbsListView.obtainView(AbsListView.java:2424)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.widget.ListView.makeAndAddView(ListView.java:1781)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.widget.ListView.fillDown(ListView.java:679)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.widget.ListView.fillFromTop(ListView.java:739)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.widget.ListView.layoutChildren(ListView.java:1632)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at au.drp.mylistview.draganddrop.DragSortListView.layoutChildren(DragSortListView.java:961)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.widget.AbsListView.onLayout(AbsListView.java:2254)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.view.View.layout(View.java:11467)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.view.ViewGroup.layout(ViewGroup.java:4237)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.widget.FrameLayout.onLayout(FrameLayout.java:431)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.view.View.layout(View.java:11467)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.view.ViewGroup.layout(ViewGroup.java:4237)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1644)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1502)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.widget.LinearLayout.onLayout(LinearLayout.java:1415)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.view.View.layout(View.java:11467)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.view.ViewGroup.layout(ViewGroup.java:4237)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.widget.FrameLayout.onLayout(FrameLayout.java:431)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.view.View.layout(View.java:11467)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.view.ViewGroup.layout(ViewGroup.java:4237)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1721)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2678)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.os.Handler.dispatchMessage(Handler.java:99)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.os.Looper.loop(Looper.java:137)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at android.app.ActivityThread.main(ActivityThread.java:4514)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at java.lang.reflect.Method.invokeNative(Native Method)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at java.lang.reflect.Method.invoke(Method.java:511)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:993)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:760)
08-02 09:53:37.090: E/AndroidRuntime(16119):    at dalvik.system.NativeStart.main(Native Method)

但是我发现通过更改DragSortListView类中的错误部分,我可以更改结果但仍然是相对布局类型和列表视图之间的强制转换异常错误。我谈到的这一部分是DragSortListView类的以下getView代码。我尝试改变的是RelativeLayout变量类型并转换为CheckableRelativelayout。

注意:我在代码“//不喜欢这个语句代码”中的注释是错误行

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

  RelativeLayout v;
  View child;

  //Log.d("mobeta", "getView: position="+position+" convertView="+convertView);
  if (convertView != null) {

    v = (RelativeLayout) convertView;
    View oldChild = v.getChildAt(0);

    //child = super.getView(position, oldChild, v);
    child = mAdapter.getView(position, oldChild, v);
    if (child != oldChild) {
      // shouldn't get here if user is reusing convertViews properly
      v.removeViewAt(0);
      v.addView(child);
      // check that tags are equal too?
      v.setTag(child.findViewById(R.id.drag));
    }

  } else {
    AbsListView.LayoutParams params =
      new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    v = new RelativeLayout(getContext());
    v.setLayoutParams(params);
    child = mAdapter.getView(position, null, v);  //DOES NOT LIKE THIS STATEMENT CODE
    v.addView(child);

    v.setTag(child.findViewById(R.id.drag));
  }

这是我的适配器类的getView

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // This is how you would determine if this particular item is checked
    // when the view gets created
    // --       
    final DragSortListView lv = (DragSortListView) parent;  // DOES NOT LIKE THIS STATEMENT CODE
    final boolean isChecked = lv.isItemChecked(position);

    // Get the listview Choice Mode
    //
    final int selectionMode = lv.getChoiceMode();

    // The item we want to get the view for
    // --
    Item currentItem = getItem(position);

    // Re-use the view if possible (recycle)
    // --
    ViewHolder holder = null;
    //final View mView = mInflator.inflate(R.layout.listview_row, null);
    if (convertView == null) {
        convertView = mInflator.inflate(R.layout.listview_row, null);
        holder = new ViewHolder();
        holder.txtTitle = (TextView) convertView.findViewById(R.id.title);
        holder.txtDescription = (TextView) convertView.findViewById(R.id.description);
        holder.txtSessionCount = (TextView) convertView.findViewById(R.id.session_count);
        holder.listThumbnailImage = (ImageView) convertView.findViewById(R.id.list_image);
        holder.listStatusIndicatorImage = (ImageView) convertView.findViewById(R.id.drag);
        holder.Checkbox = (InertCheckBox) convertView.findViewById(R.id.inertCheckBox);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder)convertView.getTag();
    }
    // End recycler
    //

    holder.txtTitle.setText(currentItem.getTitle());
    holder.txtDescription.setText(currentItem.getDescription());
    holder.txtSessionCount.setText(currentItem.getSessionCount());
    holder.listThumbnailImage.setImageBitmap((Bitmap) currentItem.getThumbnailImage());

    // Now the Status ImageView and/or the InertCheckBox view
    switch (selectionMode) {
    case ListView.CHOICE_MODE_NONE:
        holder.Checkbox.setVisibility(InertCheckBox.INVISIBLE);
        holder.listStatusIndicatorImage.setVisibility(ImageView.VISIBLE);

        holder.listStatusIndicatorImage.setAdjustViewBounds(true);
        holder.listStatusIndicatorImage.setMaxHeight(48);
        holder.listStatusIndicatorImage.setMaxWidth(48);
        if (!dndMode) {
            holder.listStatusIndicatorImage.setImageBitmap((Bitmap) currentItem.getListIndicatorImage());

        } else {
            holder.listStatusIndicatorImage.setImageResource(R.drawable.list_icon_reorder_holo_dark);
        }   
        holder.listStatusIndicatorImage.setScaleType(ScaleType.CENTER_INSIDE);
        break;
    case ListView.CHOICE_MODE_SINGLE: case ListView.CHOICE_MODE_MULTIPLE:
        MyListViewAdapter.dndMode = false;
        holder.listStatusIndicatorImage.setVisibility(ImageView.INVISIBLE);
        holder.Checkbox.setVisibility(InertCheckBox.VISIBLE);
        if (!chkbxDelete) {
            holder.Checkbox.setButtonDrawable(R.drawable.checkbox);
        } else {
            holder.Checkbox.setButtonDrawable(R.drawable.checkboxdelete);
        }
        holder.Checkbox.setChecked(isChecked);
        break;
    }           

    return convertView;
}

我的列表视图行布局

<?xml version="1.0" encoding="utf-8"?>
<au.drp.mylistview.widget.CheckableRelativeLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:drp="http://schemas.android.com/apk/res/au.drp.mylistview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/list_selector"
android:orientation="horizontal"
android:padding="2dip" >

<!-- ListRow Left side Thumbnail image -->

<LinearLayout
    android:id="@+id/thumbnail"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:layout_marginRight="5dip"
    android:gravity="center_vertical"
    android:padding="3dip" >

    <ImageView
        android:id="@+id/list_image"
        android:layout_width="50dip"
        android:layout_height="50dip"
        android:src="@drawable/icon" >
    </ImageView>
</LinearLayout>

<!-- Title Of Exercise -->
<TextView
    android:id="@+id/title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignTop="@+id/thumbnail"
    android:layout_toLeftOf="@+id/inertCheckBox"
    android:layout_toRightOf="@+id/thumbnail"
    android:text="This is the Title - Testing 1 2 3 "
    android:textColor="#ffffffff"
    android:textSize="18dip"
    android:textStyle="bold"
    android:typeface="sans" />

<TextView
    android:id="@+id/description"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/title"
    android:layout_toLeftOf="@+id/inertCheckBox"
    android:layout_toRightOf="@id/thumbnail"
    android:text="this is the description - Testing 1 2 3"
    android:textColor="#ffcccccc"
    android:textSize="14dip" />

<TextView
    android:id="@+id/session_count"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:layout_alignParentTop="true"
    android:gravity="right"
    android:text="100"
    android:textColor="#ffcccccc"
    android:textSize="10dip"
    android:textStyle="bold" />
<ImageView
    android:id="@+id/drag"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignBottom="@id/inertCheckBox"
    android:layout_alignLeft="@id/inertCheckBox"
    android:layout_alignParentRight="true"
    android:layout_alignTop="@id/inertCheckBox"
    android:layout_below="@id/session_count"
    android:layout_centerVertical="false"
    android:adjustViewBounds="true"
    android:maxHeight="32dip"
    android:maxWidth="32dip"
    android:scaleType="center"
    android:src="@drawable/arrow_32_holo_dark"
    android:visibility="visible" />
<au.drp.mylistview.widget.InertCheckBox
    android:id="@+id/inertCheckBox"
    style="@drawable/checkbox"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:layout_below="@id/session_count"
    android:button="@drawable/checkbox"
    android:checked="true"
    android:clickable="false"
    android:focusable="false"
    android:focusableInTouchMode="false" />

</au.drp.mylistview.widget.CheckableRelativeLayout>

我的CheckableRelativeLayout类

public class CheckableRelativeLayout extends RelativeLayout implements Checkable {

private boolean isChecked;
private List<Checkable> checkableViews;

public CheckableRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    initialise(attrs);
}

public CheckableRelativeLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    initialise(attrs);
}

public CheckableRelativeLayout(Context context, int checkableId) {
    super(context);
    initialise(null);
}

/*
 * @see android.widget.Checkable#isChecked()
 */
public boolean isChecked() {
    return isChecked;
}

/*
 * @see android.widget.Checkable#setChecked(boolean)
 */
public void setChecked(boolean isChecked) {
    this.isChecked = isChecked;
    for (Checkable c : checkableViews) {
        c.setChecked(isChecked);
    }
}

/*
 * @see android.widget.Checkable#toggle()
 */
public void toggle() {
    this.isChecked = !this.isChecked;
    for (Checkable c : checkableViews) {
        c.toggle();
    }
}

@Override
protected void onFinishInflate() {
    super.onFinishInflate();

    final int childCount = this.getChildCount();
    for (int i = 0; i < childCount; ++i) {
        findCheckableChildren(this.getChildAt(i));
    }
}

/**
 * Read the custom XML attributes
 */
private void initialise(AttributeSet attrs) {
    this.isChecked = false;
    this.checkableViews = new ArrayList<Checkable>(5);
}

/**
 * Add to our checkable list all the children of the view that implement the
 * interface Checkable
 */
private void findCheckableChildren(View v) {
    if (v instanceof Checkable) {
        this.checkableViews.add((Checkable) v);
    }

    if (v instanceof ViewGroup) {
        final ViewGroup vg = (ViewGroup) v;
        final int childCount = vg.getChildCount();
        for (int i = 0; i < childCount; ++i) {
            findCheckableChildren(vg.getChildAt(i));
        }
    }
}

}

以及DragsortListView的自定义列表视图布局

<?xml version="1.0" encoding="utf-8"?>
<au.drp.mylistview.draganddrop.DragSortListView
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:dslv="http://schemas.android.com/apk/res/au.drp.mylistview"
  android:id="@android:id/list"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:paddingTop="20dp"
  android:paddingBottom="20dp"
  dslv:collapsed_height="5dp"
  dslv:drag_scroll_start="0.33"
  dslv:max_drag_scroll_speed="0.5"
  dslv:float_background_color="#000000"
  dslv:remove_mode="none"
  dslv:track_drag_scroll="false" />

有人能够向我指出我的错误吗?我被卡住了。

谢谢,

保罗。

java android android-layout android-widget
2个回答
0
投票

好的,我发现了问题!但提出了另一个问题。问题是我的MyListViewAdapter类中的这一行

 final ListView lv = (ListView) parent;  // DOES NOT LIKE THIS STATEMENT CODE

如果我发表评论并使用lv的所有内容运行并拖放工作!但现在的问题是如何确定列表视图中的项是否被选中?因此,如果检查视图,这就是我获取的方式

    // This is how you would determine if this particular item is checked
    // when the view gets created
    // --       
    final ListView lv = (ListView) parent;  // DOES NOT LIKE THIS STATEMENT CODE
    final boolean isChecked = lv.isItemChecked(position);

    // Get the listview Choice Mode
    //
    final int selectionMode = lv.getChoiceMode();

我想我可以在代码中添加一个if语句,用于何时使用拖放支持模式,但这似乎是一种解决方法。有任何想法吗?


0
投票

传递到View parentgetView参数不是包含列表的ListView,它只是convertView的父级(即,用于膨胀)。从根本上说,这不是一个ListView对象,这就是为什么你在尝试施放它时得到一个ClassCastException,因为它不能被施放到ListView。你应该将ListView对象传递给Adapter sublcass的构造函数,然后在getView中使用它。


0
投票

在我的情况下ClassCastException是因为在my_custom_view.xml(我用它来膨胀MyCustomView)我已经定义了它的id

android:id="@+id/myCustomView"

然后在my_activity.xml我再次定义了它的id

<com.example.app.views.custom.MyCustomView
        android:id="@+id/myCustomView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

id中删除my_custom_view.xml参数解决了这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.