所以我正在编写一个自定义列表视图&适配器在列表视图中显示我自己的自定义项行。我有一个功能列表视图,其功能是在选择模式之间切换,并通过列表视图行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" />
有人能够向我指出我的错误吗?我被卡住了。
感谢,
保罗。
答案 0 :(得分: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语句,用于何时使用拖放支持模式,但这似乎是一种解决方法。有什么想法吗?
答案 1 :(得分:0)
View parent
的 getView
参数不是包含列表的ListView
,它只是convertView
的父级(即,用于充气)。从根本上说,这不是ListView
对象,这就是为什么在尝试投射时获得ClassCastException
的原因,因为它无法转换为ListView
。您应该将ListView
对象传递到Adapter
sublcass的构造函数,然后在getView
中使用它。
答案 2 :(得分: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
参数解决了该问题。