我需要一个带有可扩展RecyclerView的Activity,如下图所示:
所以我使用this third party library project。 该部分有效。
当我在接下来的两段中完成我所描述的内容时,问题出现了:
我的下一个要求是我希望不同的父行有不同的子行。我正在复制(如果那是正确的话)this example to create multiple child-viewholders。
示例说明: 这个想法基本上是让不同的子视图符号(对应于每个子行样式)扩展一个共同的子视图持有者,然后在我们的ExpandableRecyclerAdapter中,我们传递构造函数(SSCCE中的parentItemList
)中父行中显示的数据的ArrayList,我们声明表示所有子行类型的常量(下面SSCCE中的TYPE_EDITTEXT和TYPE_SPINNER) );然后在getItemViewType(int position)
内部,我们使用传递的parentItemList
作为索引来比较来自int position
的数据项,每个文本字符串都在父行上,并且在每种情况下,分配viewType
} int变量一个TYPE常量,viewType
。然后这个int viewType
被传递给onCreateChildViewHolder
和onBindChildViewHolder
,所以我们在每个的定义中执行另一个switch-block这些方法然后在onCreateChildViewHolder中我们返回一个相应的ChildViewHolder(从相应的布局资源中膨胀)(SSCCE中的R.layout.custom_row_child_with_edittext
或R.layout.custom_row_child_with_spinner
);并在onBindChildViewHolder
中,根据switch-block中的大小写更新数据。
问题是多才多艺的ClassCastException:
07-26 18:21:54.380: E/AndroidRuntime(276): FATAL EXCEPTION: main
07-26 18:21:54.380: E/AndroidRuntime(276): java.lang.ClassCastException: tests.test.epmc_mobile.search_module.no_ui.expandable_recycler_view.EPMCChildViewHolder
07-26 18:21:54.380: E/AndroidRuntime(276): at com.bignerdranch.expandablerecyclerview.Adapter.ExpandableRecyclerAdapter.onBindViewHolder(ExpandableRecyclerAdapter.java:144)
问题是ExpandableRecyclerAdapter.java是第三方图书馆项目的一部分,第144行(以及我添加的142和143)是:
Log.i(TAG, "+++++++++++++++++++++++++THE TYPE OF THE RecyclerView.ViewHolder WHICH HAS BEEN PASSED AS AN ARGUMENT IS "
+ holder.getClass().getSimpleName() + "++++++++++++++++++++++++++++");
PVH parentViewHolder = (PVH) holder;
在我尝试做上面的工作之前,它工作正常。
MainActivity.java
public class MainActivity extends FragmentActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private RecyclerView recyclerView;
private static int [] imageIds = {R.drawable.ic_action_call, R.drawable.ic_action_copy, R.drawable.ic_action_discard};
private static String [] titles = {"Dummy Text One", "Dummy Text Two", "Dummy Text Three"};
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "onCreate of MainActivity called.");//check
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.mainActivity_recyclerView);
MyExpandableRecyclerAdapter myExpandableRecyclerAdapter = new MyExpandableRecyclerAdapter(this, populateDataList(this));
recyclerView.setAdapter(myExpandableRecyclerAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
private ArrayList<ParentObject> populateDataList(Context context) {
Log.i(TAG, "populateDataList of MainActivity called.");//check
ArrayList<ParentObject> parentObjectList = new ArrayList<>();
for (int i=0; i<imageIds.length && i<titles.length; i++) {
MyCustomParentObject myCustomParentObject = new MyCustomParentObject(context);
myCustomParentObject.setImageId(imageIds[i]);
myCustomParentObject.setTitle(titles[i]);
parentObjectList.add(myCustomParentObject);
}
return parentObjectList;
}
}
MyExpandableRecyclerAdapter.java
public class MyExpandableRecyclerAdapter extends ExpandableRecyclerAdapter<ParentViewHolder, ChildViewHolder> {
private static final String TAG = MyExpandableRecyclerAdapter.class.getSimpleName();
LayoutInflater layoutInflater;
Context context;
private List<ParentObject> parentItemList = new ArrayList<>();
private static final int TYPE_EDITTEXT = 0;
private static final int TYPE_SPINNER = 1;
public MyExpandableRecyclerAdapter(Context context, List<ParentObject> parentObjectItemsList) {
super(context, parentObjectItemsList);
Log.i(TAG, "Constructor of MyExpandableRecyclerAdapter called.");//check
layoutInflater = LayoutInflater.from(context);
this.context = context;
parentItemList = parentObjectItemsList;
}
@Override
public int getItemViewType(int position) {
int viewType;
if (parentItemList.get(position).equals("EditText Entry")) {
viewType = TYPE_EDITTEXT;
} else {
viewType = TYPE_SPINNER;
}
return viewType;
}
@Override
public MyParentViewHolder onCreateParentViewHolder(ViewGroup container, int viewType) {
Log.i(TAG, "onCreateParentViewHolder of MyExpandableRecyclerAdapter called.");//check
Log.i(TAG, "IN onCreateParentViewHolder, THE TYPE OF AN ITEM IN THE parentItemList IS " + parentItemList.get(1));
return new MyParentViewHolder(layoutInflater.inflate(R.layout.custom_row_parent, container, false));
}
@Override
public MyChildViewHolder onCreateChildViewHolder(ViewGroup container, int viewType) {
Log.i(TAG, "onCreateChildViewHolder of MyExpandableRecyclerAdapter called.");//check
switch(viewType) {
case TYPE_EDITTEXT:
return new MyChildViewHolder(layoutInflater.inflate(R.layout.custom_row_child_with_edittext, container, false), context);
case TYPE_SPINNER:
return new MyChildViewHolder(layoutInflater.inflate(R.layout.custom_row_child_with_spinner, container, false), context);
default:
return new MyChildViewHolder(layoutInflater.inflate(R.layout.custom_row_child_with_edittext, container, false), context);
}
}
@Override
public void onBindParentViewHolder(ParentViewHolder parentViewHolder, int position, Object parentObject) {
Log.i(TAG, "onBindParentViewHolder of MyExpandableRecyclerAdapter called.");//check
MyParentViewHolder myParentViewHolder = (MyParentViewHolder) parentViewHolder;
MyCustomParentObject myCustomParentObject = (MyCustomParentObject) parentObject;
myParentViewHolder.textView.setText(myCustomParentObject.getTitle());
myParentViewHolder.imageView.setImageResource(myCustomParentObject.getImageId());
}
@Override
public void onBindChildViewHolder(ChildViewHolder childViewHolder, int position, Object childObject) {
Log.i(TAG, "onBindChildViewHolder of MyExpandableRecyclerAdapter called.");//check
switch(childViewHolder.getItemViewType()) {
case TYPE_EDITTEXT:
MyChildViewHolderWithEditText myChildViewHolderWithEditText = (MyChildViewHolderWithEditText) childViewHolder;
myChildViewHolderWithEditText.textView.setText("TextView " + (position+1) + " Title");
case TYPE_SPINNER:
MyCustomChildObject myCustomChildObject = (MyCustomChildObject) childObject;
ArrayAdapter arrayAdapter = new ArrayAdapter(context, android.R.layout.simple_list_item_1, myCustomChildObject.getSpinnerItems());
arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
MyChildViewHolderWithSpinner myChildViewHolderWithSpinner = (MyChildViewHolderWithSpinner) childViewHolder;
myChildViewHolderWithSpinner.spinner.setAdapter(arrayAdapter);
}
}
}
MyCustomParentObject.java
public class MyCustomParentObject implements ParentObject {
private static final String TAG = MyCustomParentObject.class.getSimpleName();
//List to store all the children of the parent object in.
private List<Object> childObjectList;
private String [] bib;
MyCustomParentObject (Context context) {
super();
bib = context.getResources().getStringArray(R.array.spinner_options);
}
@Override
public List<Object> getChildObjectList() {
Log.i(TAG, "getChildObjectList of MyCustomParentObject called.");//check
//"You can either return a newly created list of children here or attach them later"
return populateChildObjectList();
}
@Override
public void setChildObjectList(List<Object> childObjectList) {
Log.i(TAG, "setChildObjectList of MyCustomParentObject called.");//check
childObjectList = childObjectList;
}
private List<Object> populateChildObjectList() {
Log.i(TAG, "populateChildObjectList of MyCustomParentObject called.");//check
childObjectList = new ArrayList<>();
MyCustomChildObject myCustomChildObject = new MyCustomChildObject();
myCustomChildObject.setSpinnerItems(bib);
Object myCustomChildObjectCasted = (Object) myCustomChildObject;
childObjectList.add(myCustomChildObjectCasted);
return childObjectList;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private int imageId;
private String title;
public int getImageId() {
Log.i(TAG, "getImageId of MyCustomParentObject called.");//check
return imageId;
}
public void setImageId(int imageId) {
Log.i(TAG, "setImageId of MyCustomParentObject called.");//check
this.imageId = imageId;
}
public String getTitle() {
Log.i(TAG, "getTitle of MyCustomParentObject called.");//check
return title;
}
public void setTitle(String title) {
Log.i(TAG, "setTitle of MyCustomParentObject called.");//check
this.title = title;
}
}
MyCustomChildObject.java
public class MyCustomChildObject {
private static final String TAG = MyCustomParentObject.class.getSimpleName();
private String [] spinnerItems;
public String [] getSpinnerItems() {
return spinnerItems;
}
public void setSpinnerItems(String [] spinnerItems) {
this.spinnerItems = spinnerItems;
}
}
MyCustomParentViewHolder.java
public class MyParentViewHolder extends ParentViewHolder {
private static final String TAG = MyParentViewHolder.class.getSimpleName();
TextView textView;
ImageView imageView;
public MyParentViewHolder(View itemView) {
super(itemView);
Log.i(TAG, "Constructor of MyParentViewHolder called.");//check
textView = (TextView) itemView.findViewById(R.id.parentCustomRow_textView);
imageView = (ImageView) itemView.findViewById(R.id.parentCustomRow_imageView);
}
}
MyCustomChildViewHolder.java
public class MyChildViewHolder extends ChildViewHolder {
private static final String TAG = MyChildViewHolder.class.getSimpleName();
public MyChildViewHolder(View itemView, final Context context) {
super(itemView);
Log.i(TAG, "Constructor of MyChildViewHolder called.");// check
}
}
MyCustomChildViewHolderWithEditText.java
public class MyChildViewHolderWithEditText extends MyChildViewHolder {
EditText editText;
TextView textView;
public MyChildViewHolderWithEditText(View itemView, Context context) {
super(itemView, context);
textView = (TextView) itemView.findViewById(R.id.childViewHolderWithEditText_TextView);
editText = (EditText) itemView.findViewById(R.id.childViewHolderWithEditText_editText);
}
}
MyCustomChildViewHolderWithSpinner.java
public class MyChildViewHolderWithSpinner extends MyChildViewHolder {
Spinner spinner;
public MyChildViewHolderWithSpinner(View itemView, Context context) {
super(itemView, context);
spinner = (Spinner) itemView.findViewById(R.id.childViewHolderWithSpinner_spinner);
//ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(context, R.array.childViewSpinnerFields, android.R.layout.simple_spinner_item);
//adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
///spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {}
@Override
public void onNothingSelected(AdapterView<?> parent) {}
});
}
}
答案 0 :(得分:0)
通过比较Line#13 of this stack-trace of the error free program和this one of the program which results in the exception,并查看Line#117 of this ExpandableRecyclerAdapter.java
class上的onCreateViewHolder(ViewGroup viewGroup, int viewType)
方法定义,我从中推断onCreateViewHolder
正在传递错误的viewType
参数。
但我还没弄清楚原因!
我认为我已经弄清楚了。
实际上我在TYPE_SOMETHING
中使用的MyExpandableRecyclerAdapter
常量技巧与他们在ExpandableRecyclerAdapter
中使用的相同,即在MyExpandableRecyclerAdapter
,{{1} }是0
的值,TYPE_EDITTEXT
是1
的值;而在我TYPE_SPINNER
扩展的ExpandableRecyclerAdapter
中,MyExpandableRecyclerAdapter
的{{1}}值是0
,而TYPE_PARENT
的值是1
。
如果Android框架将相同的TYPE_CHILD
参数传递给viewType
,onCreateViewHolder
会从getItemViewType(int position)
返回1
,如果它是TYPE_SPINNER
MyExpandableRecyclerAdapter
,但他们的ExpandableRecyclerAdapter
会将其理解为TYPE_CHILD
,从而致电onCreateChildViewHolder
。
所以我认为我想要完成的所有事情都无法完成。 =(强>