Java Android RecyclerView项目在滚动中随机移动
my multiple view type RecyclerView Adapter的项目/单元格在滚动条上进行随机移动。我列举了以下所有可能的解决方案,但没有一个有效 一,Java Android RecyclerView项目在滚动中随机移动,java,android,android-recyclerview,Java,Android,Android Recyclerview,my multiple view type RecyclerView Adapter的项目/单元格在滚动条上进行随机移动。我列举了以下所有可能的解决方案,但没有一个有效 一, 增加了RecyclerView的缓存 如果有人有任何解决方案,请分享 我的适配器类 public class FormAdapter extends RecyclerView.Adapter<BaseViewHolder> { private Context mContext; private List&l
public class FormAdapter extends RecyclerView.Adapter<BaseViewHolder> {
private Context mContext;
private List<BaseFormElement> mDataset;
public FormAdapter(Context context) {
mContext = context;
mDataset = new ArrayList<>();
setHasStableIds(true);
}
public List<BaseFormElement> getDataset() {
return mDataset;
}
public OnFormElementValueChangedListener getValueChangeListener() {
return mListener;
}
@Override
public int getItemCount() {
return mDataset.size();
}
@Override
public int getItemViewType(int position) {
return mDataset.get(position).getType();
}
@Override
public long getItemId(int position) {
//return super.getItemId(position);
return mDataset.get(position).getBaseFormElementId();
}
@NonNull
@Override
public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// get layout based on header or element type
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View v;
switch (viewType) {
case BaseFormElement.TYPE_HEADER:
v = inflater.inflate(R.layout.form_element_header, parent, false);
return new FormElementHeader(v);
case BaseFormElement.TYPE_EDIT_TEXT:
v = inflater.inflate(R.layout.form_element, parent, false);
return new FormElementEditTextViewHolder(v, new FormItemEditTextListener(this));
case BaseFormElement.TYPE_PICKER_DATE:
v = inflater.inflate(R.layout.form_element, parent, false);
return new FormElementPickerDateViewHolder(v, mContext, this);
case BaseFormElement.TYPE_PICKER_TIME:
v = inflater.inflate(R.layout.form_element, parent, false);
return new FormElementPickerTimeViewHolder(v, mContext, this);
case BaseFormElement.TYPE_PICKER_SINGLE:
v = inflater.inflate(R.layout.form_element, parent, false);
return new FormElementPickerSingleViewHolder(v, mContext, this, new FormItemEditTextListener(this));
case BaseFormElement.TYPE_PICKER_MULTI:
v = inflater.inflate(R.layout.formelementlabel, parent, false);
return new FormElementPickerMultiViewHolder(v, mContext, this);
case BaseFormElement.TYPE_IMAGE_REMARKS:
v = inflater.inflate(R.layout.formelementlabel, parent, false);
return new FormElementImageWithRemarksViewHolder(v, mContext, this);
case BaseFormElement.TYPE_SWITCH:
v = inflater.inflate(R.layout.form_element_switch, parent, false);
return new FormElementSwitchViewHolder(v, mContext, this);
case BaseFormElement.TYPE_SEGMENT:
v = inflater.inflate(R.layout.form_element_switch, parent, false);
return new FormElementSwitchViewHolder(v, mContext, this);
case BaseFormElement.TYPE_LABEL:
v = inflater.inflate(R.layout.formelementlabel, parent, false);
return new FormElementLabelViewHolder(v, clicklistner);
case BaseFormElement.TYPE_IMAGE:
v = inflater.inflate(R.layout.formelementlabel, parent, false);
return new FromElementImageViewHolder(v, mContext, this);
case BaseFormElement.TYPE_VIDEO:
v = inflater.inflate(R.layout.formelementlabel, parent, false);
return new FormElementVideoViewHolder(v, mContext, this);
case BaseFormElement.DIALOG_LIST:
v = inflater.inflate(R.layout.form_element_mmv, parent, false);
return new FormElementDialogListViewHolder(v, mContext, this);
case BaseFormElement.TYPE_SLIDER:
v = inflater.inflate(R.layout.formelementlabel, parent, false);
return new FormElementSliderViewHolder(v, mContext, this);
default:
v = inflater.inflate(R.layout.form_element, parent, false);
return new FormElementEditTextViewHolder(v, new FormItemEditTextListener(this));
}
}
@Override
public void onBindViewHolder(BaseViewHolder holder, final int position) {
// gets current object
BaseFormElement currentObject = mDataset.get(position);
holder.bind(position, currentObject, mContext);
}
公共类FormAdapter扩展了RecyclerView.Adapter{
私有上下文;
私有列表数据集;
公共FormAdapter(上下文){
mContext=上下文;
mDataset=newarraylist();
setHasStableIds(true);
}
公共列表getDataset(){
返回mDataset;
}
public OnFormElementValueChangedListener getValueChangeListener(){
返回链接器;
}
@凌驾
public int getItemCount(){
返回mDataset.size();
}
@凌驾
public int getItemViewType(int位置){
返回mDataset.get(position.getType();
}
@凌驾
公共长getItemId(int位置){
//返回super.getItemId(位置);
返回mDataset.get(position.getBaseFormElementId();
}
@非空
@凌驾
public BaseViewHolder onCreateViewHolder(视图组父级,int-viewType){
//根据标题或元素类型获取布局
LayoutInflater充气器=LayoutInflater.from(parent.getContext());
观点五;
开关(视图类型){
案例BaseFormElement.TYPE_标题:
v=充气机充气(R.layout.form\u element\u标题,父项,false);
返回新的FormElementHeader(v);
case BaseFormElement.TYPE\u EDIT\u文本:
v=充气机充气(R.layout.form_元素,父元素,假);
返回新FormElementEditTextViewHolder(v,新FormItemEditTextListener(this));
case BaseFormElement.TYPE\u PICKER\u日期:
v=充气机充气(R.layout.form_元素,父元素,假);
返回新的FormElement PickerDateViewHolder(v、McContext、this);
案例BaseFormElement.TYPE\u选取器\u时间:
v=充气机充气(R.layout.form_元素,父元素,假);
返回新的FormElement PickerTimeViewHolder(v、McContext、this);
case BaseFormElement.TYPE_PICKER_SINGLE:
v=充气机充气(R.layout.form_元素,父元素,假);
返回新的FormElementPickerSingleViewHolder(v,mContext,this,new FormItemEditTextListener(this));
case BaseFormElement.TYPE\u PICKER\u MULTI:
v=充气机。充气(R.layout.formelementlabel,父项,false);
返回新的FormElement PickerMultiViewHolder(v、mContext、this);
case BaseFormElement.TYPE_IMAGE_备注:
v=充气机。充气(R.layout.formelementlabel,父项,false);
返回带有RemarksViewHolder的新FormElement图像(v、McContext、this);
case BaseFormElement.TYPE_开关:
v=充气机充气(R.layout.form\u element\u开关,父级,错误);
返回新的FormElementSwitchViewHolder(v、mContext、this);
case BaseFormElement.TYPE_段:
v=充气机充气(R.layout.form\u element\u开关,父级,错误);
返回新的FormElementSwitchViewHolder(v、mContext、this);
case BaseFormElement.TYPE_标签:
v=充气机。充气(R.layout.formelementlabel,父项,false);
返回新的FormElementLabelViewer文件夹(v,单击列表器);
case BaseFormElement.TYPE_图像:
v=充气机。充气(R.layout.formelementlabel,父项,false);
返回新的FromElementImageViewHolder(v,mContext,this);
case BaseFormElement.TYPE_视频:
v=充气机。充气(R.layout.formelementlabel,父项,false);
返回新的FormElementVideoViewHolder(v、McContext、this);
案例BaseFormElement.DIALOG\u列表:
v=充气机。充气(R.layout.form\u element\u mmv,父项,false);
返回新的FormElementDialogListViewHolder(v、McContext、this);
case BaseFormElement.TYPE_滑块:
v=充气机。充气(R.layout.formelementlabel,父项,false);
返回新的FormElementSliderViewHolder(v,mContext,this);
违约:
v=充气机充气(R.layout.form_元素,父元素,假);
返回新FormElementEditTextViewHolder(v,新FormItemEditTextListener(this));
}
}
@凌驾
公共无效onBindViewHolder(BaseViewHolder,最终int位置){
//获取当前对象
BaseFormElement currentObject=mDataset.get(位置);
holder.bind(位置、当前对象、mContext);
}
}使RecyclerView视图模型不可回收。我认为默认情况下,recyclerview设置为刷新,因此,对项目进行洗牌 比如说
class YourViewModel extends RecyclerView.ViewHolder {
YourViewModel (@NonNull View view) {
super(view);
// Add the line below
this.setIsRecyclable(false);
}
}
此外,您还可以在填充项之前使用Collection.sort(项)实现排序方法,因此即使视图被回收,项仍然保持排序(例如按id)。您可以尝试:
@Override
public long getItemId(int position) {
return position;
}
还覆盖:
@Override
public int getItemViewType(int position) {
return position;
}
增加recyclerview缓存的一种方法是:
recyclerView.setItemViewCacheSize(20)
您还可以借助LinearLayoutManager的方法获得额外的空间。我已经添加了文档的链接
或者,您可以使用:
setIsRecyclable(false);
但是它超出了使用RecyclerView的目的。您不应该使用
hashCode()
作为ID,因为它不能保证是唯一的!
我猜您的许多项目都返回相同的哈希值。
请尝试为每个项目实现一个唯一的ID,并在您的
getItemId()
方法中使用它。我已经研究过这种类型的RecyclerView
,下面是与多个视图类型一起使用的DynamicAdapter
类。我希望你能弄清楚如何使用它
public class DynamicAdapter extends RecyclerView.Adapter <BaseViewHolder> {
private static final String TAG = "DynamicAdapter";
private static final int VIEW_EMPTY = 0;
private static final int VIEW_EDIT_TEXT = 1;
private static final int VIEW_SIGNATURE = 2;
private static final int VIEW_UPLOAD = 3;
private static final int VIEW_DATE_TIME = 4;
private static final int VIEW_DATE_RANGE = 5;
private static final int VIEW_DATE = 6;
private static final int VIEW_DESCRIPTION = 7;
private static final int VIEW_UNDEFINED = 8;
ArrayList <FormData> formDataList;
private Context context;
private AdapterListener adapterListener;
public DynamicAdapter(ArrayList <FormData > formDataList) {
this.formDataList = formDataList;
}
public void setAdapterListener(AdapterListener adapterListener) {
this.adapterListener = adapterListener;
}
@NonNull
@Override
public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
this.context = parent.getContext();
switch (viewType) {
case VIEW_EDIT_TEXT:
ItemDynamicFormEdittextBinding edittextBinding = ItemDynamicFormEdittextBinding
.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new EditTextViewHolder(edittextBinding);
case VIEW_NUMBER:
ItemDynamicFormNumberBinding numberBinding = ItemDynamicFormNumberBinding
.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new NumberViewHolder(numberBinding);
case VIEW_EMAIL:
ItemDynamicFormEmailBinding emailBinding = ItemDynamicFormEmailBinding
.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new EmailViewHolder(emailBinding);
case VIEW_UPLOAD:
ItemDynamicFormUploadBinding uploadBinding = ItemDynamicFormUploadBinding
.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new UploadViewHolder(uploadBinding);
case VIEW_DATE_RANGE:
ItemDynamicFormDateRangeBinding rangeBinding = ItemDynamicFormDateRangeBinding
.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new DateRangeViewHolder(rangeBinding);
case VIEW_DATE_TIME:
ItemDynamicFormDateTimeBinding dateTimeBinding = ItemDynamicFormDateTimeBinding
.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new DateTimeViewHolder(dateTimeBinding);
case VIEW_DATE:
ItemDynamicFormDateBinding dateBinding = ItemDynamicFormDateBinding
.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new DateViewHolder(dateBinding);
case VIEW_DESCRIPTION:
ItemDynamicFormDescriptionBinding descriptionBinding = ItemDynamicFormDescriptionBinding
.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new DescriptionViewHolder(descriptionBinding);
case VIEW_UNDEFINED:
ItemDynamicFormUnknownBinding unknownBinding = ItemDynamicFormUnknownBinding
.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new UnknownViewHolder(unknownBinding);
default:
ItemDynamicFormEmptyViewBinding emptyViewBinding = ItemDynamicFormEmptyViewBinding
.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new EmptyViewHolder(emptyViewBinding);
}
}
@Override
public void onBindViewHolder(@NonNull BaseViewHolder holder, final int position) {
holder.onBind(position);
}
@Override
public int getItemCount() {
return formDataList.size();
}
@Override
public int getItemViewType(int position) {
if (formDataList != null && !formDataList.isEmpty()) {
if (formDataList.get(position) != null &&
formDataList.get(position).getType() != null) {
switch (formDataList.get(position).getType()) {
case TEXT:
return VIEW_EDIT_TEXT;
case CAMERA:
return VIEW_CAMERA;
case TOGGLE:
return VIEW_TOGGLE;
case NUMBER:
return VIEW_NUMBER;
case EMAIL:
return VIEW_EMAIL;
case DATE_RANGE:
return VIEW_DATE_RANGE;
case DATE_TIME:
return VIEW_DATE_TIME;
default:
return VIEW_UNDEFINED;
}
} else {
return VIEW_UNDEFINED;
}
} else {
return VIEW_EMPTY;
}
}
/**
* Class used to handle all the text fields for email,text & number.
*/
private class EditTextViewHolder extends BaseViewHolder {
ItemDynamicFormEdittextBinding mBinding;
EditTextViewHolder(ItemDynamicFormEdittextBinding binding) {
super(binding.getRoot());
Log.e(TAG, "EditTextViewHolder: ------------>>");
this.mBinding = binding;
mBinding.edDynamicFormText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
formDataList.get(getAdapterPosition()).setEnteredValue(charSequence.toString());
}
@Override
public void afterTextChanged(Editable editable) {
}
});
}
@Override
public void onBind(int position) {
final FormData formData = formDataList.get(position);
FormEdittextViewModel emptyItemViewModel = new FormEdittextViewModel(formData);
mBinding.setViewModel(emptyItemViewModel);
// Immediate Binding
// When a variable or observable changes, the binding will be scheduled to change before
// the next frame. There are times, however, when binding must be executed immediately.
// To force execution, use the executePendingBindings() method.
mBinding.executePendingBindings();
}
}
/**
* Class used to handle all the text fields for email, text & number.
*/
private class NumberViewHolder extends BaseViewHolder {
ItemDynamicFormNumberBinding mBinding;
NumberViewHolder(ItemDynamicFormNumberBinding binding) {
super(binding.getRoot());
this.mBinding = binding;
mBinding.edDynamicFormNumber.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
formDataList.get(getAdapterPosition()).setEnteredValue(charSequence.toString());
}
@Override
public void afterTextChanged(Editable editable) {
}
});
}
@Override
public void onBind(int position) {
final FormData formData = formDataList.get(position);
mBinding.setViewModel(new FormNumberViewModel(formData));
// Immediate Binding
// When a variable or observable changes, the binding will be scheduled to change before
// the next frame. There are times, however, when binding must be executed immediately.
// To force execution, use the executePendingBindings() method.
mBinding.executePendingBindings();
}
}
/**
* Class used to handle all the text fields for email, text & number.
*/
private class EmailViewHolder extends BaseViewHolder {
ItemDynamicFormEmailBinding mBinding;
EmailViewHolder(ItemDynamicFormEmailBinding binding) {
super(binding.getRoot());
this.mBinding = binding;
mBinding.edDynamicFormEmail.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
formDataList.get(getAdapterPosition()).setEnteredValue(charSequence.toString());
}
@Override
public void afterTextChanged(Editable editable) {
}
});
}
@Override
public void onBind(int position) {
final FormData formData = formDataList.get(position);
//val radioButton = mBinding.root.findViewById(R.id.radioButtton) as RadioButton
FormEmailViewModel emptyItemViewModel = new FormEmailViewModel(formData);
mBinding.setViewModel(emptyItemViewModel);
// Immediate Binding
// When a variable or observable changes, the binding will be scheduled to change before
// the next frame. There are times, however, when binding must be executed immediately.
// To force execution, use the executePendingBindings() method.
mBinding.executePendingBindings();
}
}
/**
* Class used to handle all the text fields for description only.
*/
private class DescriptionViewHolder extends BaseViewHolder {
ItemDynamicFormDescriptionBinding mBinding;
DescriptionViewHolder(ItemDynamicFormDescriptionBinding binding) {
super(binding.getRoot());
this.mBinding = binding;
mBinding.edDynamicFormDesc.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
formDataList.get(getAdapterPosition()).setEnteredValue(charSequence.toString());
}
@Override
public void afterTextChanged(Editable editable) {
}
});
}
@Override
public void onBind(int position) {
final FormData formData = formDataList.get(position);
FormDescriptionViewModel emptyItemViewModel = new FormDescriptionViewModel(formData);
mBinding.setViewModel(emptyItemViewModel);
// Immediate Binding
// When a variable or observable changes, the binding will be scheduled to change before
// the next frame. There are times, however, when binding must be executed immediately.
// To force execution, use the executePendingBindings() method.
mBinding.executePendingBindings();
}
}
/**
* Class used to select pic form device and upload to server.
*/
private class UploadViewHolder extends BaseViewHolder
implements FormUploadViewModel.UploadListener {
private ItemDynamicFormUploadBinding mBinding;
private UploadViewHolder(ItemDynamicFormUploadBinding mBinding) {
super(mBinding.getRoot());
this.mBinding = mBinding;
}
@Override
public void onBind(int position) {
final FormData data = formDataList.get(position);
FormUploadViewModel uploadViewModel = new FormUploadViewModel(data, this);
mBinding.setViewModel(uploadViewModel);
// Immediate Binding
// When a variable or observable changes, the binding will be scheduled to change before
// the next frame. There are times, however, when binding must be executed immediately.
// To force execution, use the executePendingBindings() method.
mBinding.executePendingBindings();
}
@Override
public void onUploadClick(@NonNull FormData formData) {
adapterListener.onUploadPic(getAdapterPosition(), formData);
}
}
/**
* Class used to pick date and time.
*/
private class DateTimeViewHolder extends BaseViewHolder
implements FormDateTimeViewModel.DateTimeListener {
ItemDynamicFormDateTimeBinding mBinding;
int mYear;
int mMonth;
int mDay;
int mHour;
int mMinute;
int mSecond;
FormDateTimeViewModel dateTimeViewModel;
FormData data;
DateTimeViewHolder(ItemDynamicFormDateTimeBinding mBinding) {
super(mBinding.getRoot());
this.mBinding = mBinding;
}
@Override
public void onBind(int position) {
data = formDataList.get(position);
dateTimeViewModel = new FormDateTimeViewModel(data, this);
mBinding.setViewModel(dateTimeViewModel);
// Immediate Binding
// When a variable or observable changes, the binding will be scheduled to change before
// the next frame. There are times, however, when binding must be executed immediately.
// To force execution, use the executePendingBindings() method.
mBinding.executePendingBindings();
}
@Override
public void dateClick() {
Calendar calendar = Calendar.getInstance();
mHour = calendar.get(Calendar.HOUR_OF_DAY);
mMinute = calendar.get(Calendar.MINUTE);
mSecond = 0;
mYear = calendar.get(Calendar.YEAR);
mMonth = calendar.get(Calendar.MONTH);
mDay = calendar.get(Calendar.DAY_OF_MONTH);
CommonUtils.openDatePicker(context, mYear, mMonth, mDay,
0, 0, (view, year, monthOfYear, dayOfMonth) -> {
String selectedDate = dayOfMonth + "-" + (monthOfYear + 1) + "-" + year;
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, monthOfYear);
cal.set(Calendar.DAY_OF_MONTH, dayOfMonth);
/*cal.set(Calendar.HOUR_OF_DAY, mHour);
cal.set(Calendar.MINUTE, mMinute);
cal.set(Calendar.SECOND, 0);*/
dateTimeViewModel.getDate().set(DateTimeUtil.getParsedDate(cal.getTimeInMillis()));
data.setEnteredValue(cal.getTimeInMillis() + "");
});
}
@Override
public void timeClick() {
Calendar calendar = Calendar.getInstance();
mHour = calendar.get(Calendar.HOUR_OF_DAY);
mMinute = calendar.get(Calendar.MINUTE);
CommonUtils.openTimePicker(context, mHour, mMinute,
(view, hourOfDay, minute) -> {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, mYear);
cal.set(Calendar.MONTH, mMonth);
cal.set(Calendar.DAY_OF_MONTH, mDay);
cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
cal.set(Calendar.MINUTE, minute);
cal.set(Calendar.SECOND, 0);
dateTimeViewModel.getTime().set(DateTimeUtil.getParsedTime(cal.getTimeInMillis()));
data.setEnteredValue(cal.getTimeInMillis() + "");
});
}
}
/**
* Class used to pick date from & to .
*/
private class DateRangeViewHolder extends BaseViewHolder
implements FormDateRangeViewModel.DateRangeListener {
ItemDynamicFormDateRangeBinding mBinding;
FormDateRangeViewModel uploadViewModel;
DateRangeViewHolder(ItemDynamicFormDateRangeBinding mBinding) {
super(mBinding.getRoot());
this.mBinding = mBinding;
}
@Override
public void onBind(int position) {
FormData data = formDataList.get(position);
uploadViewModel = new FormDateRangeViewModel(data, this);
mBinding.setViewModel(uploadViewModel);
// Immediate Binding
// When a variable or observable changes, the binding will be scheduled to change before
// the next frame. There are times, however, when binding must be executed immediately.
// To force execution, use the executePendingBindings() method.
mBinding.executePendingBindings();
}
@Override
public void dateViewClick(@NotNull View view) {
// Get Current Date
Calendar c = Calendar.getInstance();
int mYear = c.get(Calendar.YEAR);
int mMonth = c.get(Calendar.MONTH);
int mDay = c.get(Calendar.DAY_OF_MONTH);
// int mHour = c.get(Calendar.HOUR_OF_DAY);
// int mMin = c.get(Calendar.MINUTE);
CommonUtils.openDatePicker(context, mYear, mMonth, mDay,
c.getTimeInMillis(), 0, (view1, year, monthOfYear, dayOfMonth) -> {
//String selectedDate = dayOfMonth + "-" + (monthOfYear + 1) + "-" + year;
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, monthOfYear);
cal.set(Calendar.DAY_OF_MONTH, dayOfMonth);
switch (view.getId()) {
case R.id.tvDateRange1:
uploadViewModel.getDate1().set(DateTimeUtil.getParsedDate(cal.getTimeInMillis()));
formDataList.get(getAdapterPosition()).setMaxRange(cal.getTimeInMillis());
break;
case R.id.tvDateRange2:
uploadViewModel.getDate2().set(DateTimeUtil.getParsedDate(cal.getTimeInMillis()));
formDataList.get(getAdapterPosition()).setMinRange(cal.getTimeInMillis());
break;
}
});
}
}
/**
* Class used to pick date
*/
private class DateViewHolder extends BaseViewHolder
implements FormDateViewModel.DateListener {
ItemDynamicFormDateBinding mBinding;
FormDateViewModel emptyItemViewModel;
int mYear, mMonth, mDay;
DateViewHolder(ItemDynamicFormDateBinding mBinding) {
super(mBinding.getRoot());
this.mBinding = mBinding;
}
@Override
public void onBind(int position) {
FormData data = formDataList.get(position);
emptyItemViewModel = new FormDateViewModel(data, this);
mBinding.setViewModel(emptyItemViewModel);
// Immediate Binding
// When a variable or observable changes, the binding will be scheduled to change before
// the next frame. There are times, however, when binding must be executed immediately.
// To force execution, use the executePendingBindings() method.
mBinding.executePendingBindings();
}
@Override
public void onDateClick() {
Calendar calendar = Calendar.getInstance();
mYear = calendar.get(Calendar.YEAR);
mMonth = calendar.get(Calendar.MONTH);
mDay = calendar.get(Calendar.DAY_OF_MONTH);
CommonUtils.openDatePicker(context, mYear, mMonth, mDay,
0, 0, (view, year, monthOfYear, dayOfMonth) -> {
// String selectedDate = dayOfMonth + "-" + (monthOfYear + 1) + "-" + year;
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, year);
c.set(Calendar.MONTH, monthOfYear);
c.set(Calendar.DAY_OF_MONTH, dayOfMonth);
formDataList.get(getAdapterPosition()).setMaxRange(c.getTimeInMillis());
emptyItemViewModel.getDate().set(DateTimeUtil.getParsedDate(c.getTimeInMillis()));
});
}
}
/**
* If hashMap is empty show empty view
*/
private class EmptyViewHolder extends BaseViewHolder
implements FormEmptyItemViewModel.ClickListener {
private ItemDynamicFormEmptyViewBinding mBinding;
EmptyViewHolder(ItemDynamicFormEmptyViewBinding binding) {
super(binding.getRoot());
this.mBinding = binding;
}
@Override
public void onBind(int position) {
FormEmptyItemViewModel emptyItemViewModel = new FormEmptyItemViewModel(this);
mBinding.setViewModel(emptyItemViewModel);
}
}
/**
* If view type is not handled then show this view
*/
private class UnknownViewHolder extends BaseViewHolder {
UnknownViewHolder(ItemDynamicFormUnknownBinding unknownBinding) {
super(unknownBinding.getRoot());
}
@Override
public void onBind(int position) {
}
}
public类DynamicAdapter扩展了RecyclerView.Adapter{
私有静态最终字符串标记=“DynamicAdapter”;
私有静态最终int视图_EMPTY=0;
私有静态最终整型视图\编辑\文本=1;
私有静态最终int视图_签名=2;
私有静态最终int视图_UPLOAD=3;
私有静态最终整数视图\日期\时间=4;
私有静态最终整数视图\日期\范围=5;
私有静态最终整数视图\u日期=
public class DynamicAdapter extends RecyclerView.Adapter <BaseViewHolder> {
private static final String TAG = "DynamicAdapter";
private static final int VIEW_EMPTY = 0;
private static final int VIEW_EDIT_TEXT = 1;
private static final int VIEW_SIGNATURE = 2;
private static final int VIEW_UPLOAD = 3;
private static final int VIEW_DATE_TIME = 4;
private static final int VIEW_DATE_RANGE = 5;
private static final int VIEW_DATE = 6;
private static final int VIEW_DESCRIPTION = 7;
private static final int VIEW_UNDEFINED = 8;
ArrayList <FormData> formDataList;
private Context context;
private AdapterListener adapterListener;
public DynamicAdapter(ArrayList <FormData > formDataList) {
this.formDataList = formDataList;
}
public void setAdapterListener(AdapterListener adapterListener) {
this.adapterListener = adapterListener;
}
@NonNull
@Override
public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
this.context = parent.getContext();
switch (viewType) {
case VIEW_EDIT_TEXT:
ItemDynamicFormEdittextBinding edittextBinding = ItemDynamicFormEdittextBinding
.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new EditTextViewHolder(edittextBinding);
case VIEW_NUMBER:
ItemDynamicFormNumberBinding numberBinding = ItemDynamicFormNumberBinding
.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new NumberViewHolder(numberBinding);
case VIEW_EMAIL:
ItemDynamicFormEmailBinding emailBinding = ItemDynamicFormEmailBinding
.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new EmailViewHolder(emailBinding);
case VIEW_UPLOAD:
ItemDynamicFormUploadBinding uploadBinding = ItemDynamicFormUploadBinding
.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new UploadViewHolder(uploadBinding);
case VIEW_DATE_RANGE:
ItemDynamicFormDateRangeBinding rangeBinding = ItemDynamicFormDateRangeBinding
.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new DateRangeViewHolder(rangeBinding);
case VIEW_DATE_TIME:
ItemDynamicFormDateTimeBinding dateTimeBinding = ItemDynamicFormDateTimeBinding
.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new DateTimeViewHolder(dateTimeBinding);
case VIEW_DATE:
ItemDynamicFormDateBinding dateBinding = ItemDynamicFormDateBinding
.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new DateViewHolder(dateBinding);
case VIEW_DESCRIPTION:
ItemDynamicFormDescriptionBinding descriptionBinding = ItemDynamicFormDescriptionBinding
.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new DescriptionViewHolder(descriptionBinding);
case VIEW_UNDEFINED:
ItemDynamicFormUnknownBinding unknownBinding = ItemDynamicFormUnknownBinding
.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new UnknownViewHolder(unknownBinding);
default:
ItemDynamicFormEmptyViewBinding emptyViewBinding = ItemDynamicFormEmptyViewBinding
.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new EmptyViewHolder(emptyViewBinding);
}
}
@Override
public void onBindViewHolder(@NonNull BaseViewHolder holder, final int position) {
holder.onBind(position);
}
@Override
public int getItemCount() {
return formDataList.size();
}
@Override
public int getItemViewType(int position) {
if (formDataList != null && !formDataList.isEmpty()) {
if (formDataList.get(position) != null &&
formDataList.get(position).getType() != null) {
switch (formDataList.get(position).getType()) {
case TEXT:
return VIEW_EDIT_TEXT;
case CAMERA:
return VIEW_CAMERA;
case TOGGLE:
return VIEW_TOGGLE;
case NUMBER:
return VIEW_NUMBER;
case EMAIL:
return VIEW_EMAIL;
case DATE_RANGE:
return VIEW_DATE_RANGE;
case DATE_TIME:
return VIEW_DATE_TIME;
default:
return VIEW_UNDEFINED;
}
} else {
return VIEW_UNDEFINED;
}
} else {
return VIEW_EMPTY;
}
}
/**
* Class used to handle all the text fields for email,text & number.
*/
private class EditTextViewHolder extends BaseViewHolder {
ItemDynamicFormEdittextBinding mBinding;
EditTextViewHolder(ItemDynamicFormEdittextBinding binding) {
super(binding.getRoot());
Log.e(TAG, "EditTextViewHolder: ------------>>");
this.mBinding = binding;
mBinding.edDynamicFormText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
formDataList.get(getAdapterPosition()).setEnteredValue(charSequence.toString());
}
@Override
public void afterTextChanged(Editable editable) {
}
});
}
@Override
public void onBind(int position) {
final FormData formData = formDataList.get(position);
FormEdittextViewModel emptyItemViewModel = new FormEdittextViewModel(formData);
mBinding.setViewModel(emptyItemViewModel);
// Immediate Binding
// When a variable or observable changes, the binding will be scheduled to change before
// the next frame. There are times, however, when binding must be executed immediately.
// To force execution, use the executePendingBindings() method.
mBinding.executePendingBindings();
}
}
/**
* Class used to handle all the text fields for email, text & number.
*/
private class NumberViewHolder extends BaseViewHolder {
ItemDynamicFormNumberBinding mBinding;
NumberViewHolder(ItemDynamicFormNumberBinding binding) {
super(binding.getRoot());
this.mBinding = binding;
mBinding.edDynamicFormNumber.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
formDataList.get(getAdapterPosition()).setEnteredValue(charSequence.toString());
}
@Override
public void afterTextChanged(Editable editable) {
}
});
}
@Override
public void onBind(int position) {
final FormData formData = formDataList.get(position);
mBinding.setViewModel(new FormNumberViewModel(formData));
// Immediate Binding
// When a variable or observable changes, the binding will be scheduled to change before
// the next frame. There are times, however, when binding must be executed immediately.
// To force execution, use the executePendingBindings() method.
mBinding.executePendingBindings();
}
}
/**
* Class used to handle all the text fields for email, text & number.
*/
private class EmailViewHolder extends BaseViewHolder {
ItemDynamicFormEmailBinding mBinding;
EmailViewHolder(ItemDynamicFormEmailBinding binding) {
super(binding.getRoot());
this.mBinding = binding;
mBinding.edDynamicFormEmail.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
formDataList.get(getAdapterPosition()).setEnteredValue(charSequence.toString());
}
@Override
public void afterTextChanged(Editable editable) {
}
});
}
@Override
public void onBind(int position) {
final FormData formData = formDataList.get(position);
//val radioButton = mBinding.root.findViewById(R.id.radioButtton) as RadioButton
FormEmailViewModel emptyItemViewModel = new FormEmailViewModel(formData);
mBinding.setViewModel(emptyItemViewModel);
// Immediate Binding
// When a variable or observable changes, the binding will be scheduled to change before
// the next frame. There are times, however, when binding must be executed immediately.
// To force execution, use the executePendingBindings() method.
mBinding.executePendingBindings();
}
}
/**
* Class used to handle all the text fields for description only.
*/
private class DescriptionViewHolder extends BaseViewHolder {
ItemDynamicFormDescriptionBinding mBinding;
DescriptionViewHolder(ItemDynamicFormDescriptionBinding binding) {
super(binding.getRoot());
this.mBinding = binding;
mBinding.edDynamicFormDesc.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
formDataList.get(getAdapterPosition()).setEnteredValue(charSequence.toString());
}
@Override
public void afterTextChanged(Editable editable) {
}
});
}
@Override
public void onBind(int position) {
final FormData formData = formDataList.get(position);
FormDescriptionViewModel emptyItemViewModel = new FormDescriptionViewModel(formData);
mBinding.setViewModel(emptyItemViewModel);
// Immediate Binding
// When a variable or observable changes, the binding will be scheduled to change before
// the next frame. There are times, however, when binding must be executed immediately.
// To force execution, use the executePendingBindings() method.
mBinding.executePendingBindings();
}
}
/**
* Class used to select pic form device and upload to server.
*/
private class UploadViewHolder extends BaseViewHolder
implements FormUploadViewModel.UploadListener {
private ItemDynamicFormUploadBinding mBinding;
private UploadViewHolder(ItemDynamicFormUploadBinding mBinding) {
super(mBinding.getRoot());
this.mBinding = mBinding;
}
@Override
public void onBind(int position) {
final FormData data = formDataList.get(position);
FormUploadViewModel uploadViewModel = new FormUploadViewModel(data, this);
mBinding.setViewModel(uploadViewModel);
// Immediate Binding
// When a variable or observable changes, the binding will be scheduled to change before
// the next frame. There are times, however, when binding must be executed immediately.
// To force execution, use the executePendingBindings() method.
mBinding.executePendingBindings();
}
@Override
public void onUploadClick(@NonNull FormData formData) {
adapterListener.onUploadPic(getAdapterPosition(), formData);
}
}
/**
* Class used to pick date and time.
*/
private class DateTimeViewHolder extends BaseViewHolder
implements FormDateTimeViewModel.DateTimeListener {
ItemDynamicFormDateTimeBinding mBinding;
int mYear;
int mMonth;
int mDay;
int mHour;
int mMinute;
int mSecond;
FormDateTimeViewModel dateTimeViewModel;
FormData data;
DateTimeViewHolder(ItemDynamicFormDateTimeBinding mBinding) {
super(mBinding.getRoot());
this.mBinding = mBinding;
}
@Override
public void onBind(int position) {
data = formDataList.get(position);
dateTimeViewModel = new FormDateTimeViewModel(data, this);
mBinding.setViewModel(dateTimeViewModel);
// Immediate Binding
// When a variable or observable changes, the binding will be scheduled to change before
// the next frame. There are times, however, when binding must be executed immediately.
// To force execution, use the executePendingBindings() method.
mBinding.executePendingBindings();
}
@Override
public void dateClick() {
Calendar calendar = Calendar.getInstance();
mHour = calendar.get(Calendar.HOUR_OF_DAY);
mMinute = calendar.get(Calendar.MINUTE);
mSecond = 0;
mYear = calendar.get(Calendar.YEAR);
mMonth = calendar.get(Calendar.MONTH);
mDay = calendar.get(Calendar.DAY_OF_MONTH);
CommonUtils.openDatePicker(context, mYear, mMonth, mDay,
0, 0, (view, year, monthOfYear, dayOfMonth) -> {
String selectedDate = dayOfMonth + "-" + (monthOfYear + 1) + "-" + year;
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, monthOfYear);
cal.set(Calendar.DAY_OF_MONTH, dayOfMonth);
/*cal.set(Calendar.HOUR_OF_DAY, mHour);
cal.set(Calendar.MINUTE, mMinute);
cal.set(Calendar.SECOND, 0);*/
dateTimeViewModel.getDate().set(DateTimeUtil.getParsedDate(cal.getTimeInMillis()));
data.setEnteredValue(cal.getTimeInMillis() + "");
});
}
@Override
public void timeClick() {
Calendar calendar = Calendar.getInstance();
mHour = calendar.get(Calendar.HOUR_OF_DAY);
mMinute = calendar.get(Calendar.MINUTE);
CommonUtils.openTimePicker(context, mHour, mMinute,
(view, hourOfDay, minute) -> {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, mYear);
cal.set(Calendar.MONTH, mMonth);
cal.set(Calendar.DAY_OF_MONTH, mDay);
cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
cal.set(Calendar.MINUTE, minute);
cal.set(Calendar.SECOND, 0);
dateTimeViewModel.getTime().set(DateTimeUtil.getParsedTime(cal.getTimeInMillis()));
data.setEnteredValue(cal.getTimeInMillis() + "");
});
}
}
/**
* Class used to pick date from & to .
*/
private class DateRangeViewHolder extends BaseViewHolder
implements FormDateRangeViewModel.DateRangeListener {
ItemDynamicFormDateRangeBinding mBinding;
FormDateRangeViewModel uploadViewModel;
DateRangeViewHolder(ItemDynamicFormDateRangeBinding mBinding) {
super(mBinding.getRoot());
this.mBinding = mBinding;
}
@Override
public void onBind(int position) {
FormData data = formDataList.get(position);
uploadViewModel = new FormDateRangeViewModel(data, this);
mBinding.setViewModel(uploadViewModel);
// Immediate Binding
// When a variable or observable changes, the binding will be scheduled to change before
// the next frame. There are times, however, when binding must be executed immediately.
// To force execution, use the executePendingBindings() method.
mBinding.executePendingBindings();
}
@Override
public void dateViewClick(@NotNull View view) {
// Get Current Date
Calendar c = Calendar.getInstance();
int mYear = c.get(Calendar.YEAR);
int mMonth = c.get(Calendar.MONTH);
int mDay = c.get(Calendar.DAY_OF_MONTH);
// int mHour = c.get(Calendar.HOUR_OF_DAY);
// int mMin = c.get(Calendar.MINUTE);
CommonUtils.openDatePicker(context, mYear, mMonth, mDay,
c.getTimeInMillis(), 0, (view1, year, monthOfYear, dayOfMonth) -> {
//String selectedDate = dayOfMonth + "-" + (monthOfYear + 1) + "-" + year;
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, monthOfYear);
cal.set(Calendar.DAY_OF_MONTH, dayOfMonth);
switch (view.getId()) {
case R.id.tvDateRange1:
uploadViewModel.getDate1().set(DateTimeUtil.getParsedDate(cal.getTimeInMillis()));
formDataList.get(getAdapterPosition()).setMaxRange(cal.getTimeInMillis());
break;
case R.id.tvDateRange2:
uploadViewModel.getDate2().set(DateTimeUtil.getParsedDate(cal.getTimeInMillis()));
formDataList.get(getAdapterPosition()).setMinRange(cal.getTimeInMillis());
break;
}
});
}
}
/**
* Class used to pick date
*/
private class DateViewHolder extends BaseViewHolder
implements FormDateViewModel.DateListener {
ItemDynamicFormDateBinding mBinding;
FormDateViewModel emptyItemViewModel;
int mYear, mMonth, mDay;
DateViewHolder(ItemDynamicFormDateBinding mBinding) {
super(mBinding.getRoot());
this.mBinding = mBinding;
}
@Override
public void onBind(int position) {
FormData data = formDataList.get(position);
emptyItemViewModel = new FormDateViewModel(data, this);
mBinding.setViewModel(emptyItemViewModel);
// Immediate Binding
// When a variable or observable changes, the binding will be scheduled to change before
// the next frame. There are times, however, when binding must be executed immediately.
// To force execution, use the executePendingBindings() method.
mBinding.executePendingBindings();
}
@Override
public void onDateClick() {
Calendar calendar = Calendar.getInstance();
mYear = calendar.get(Calendar.YEAR);
mMonth = calendar.get(Calendar.MONTH);
mDay = calendar.get(Calendar.DAY_OF_MONTH);
CommonUtils.openDatePicker(context, mYear, mMonth, mDay,
0, 0, (view, year, monthOfYear, dayOfMonth) -> {
// String selectedDate = dayOfMonth + "-" + (monthOfYear + 1) + "-" + year;
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, year);
c.set(Calendar.MONTH, monthOfYear);
c.set(Calendar.DAY_OF_MONTH, dayOfMonth);
formDataList.get(getAdapterPosition()).setMaxRange(c.getTimeInMillis());
emptyItemViewModel.getDate().set(DateTimeUtil.getParsedDate(c.getTimeInMillis()));
});
}
}
/**
* If hashMap is empty show empty view
*/
private class EmptyViewHolder extends BaseViewHolder
implements FormEmptyItemViewModel.ClickListener {
private ItemDynamicFormEmptyViewBinding mBinding;
EmptyViewHolder(ItemDynamicFormEmptyViewBinding binding) {
super(binding.getRoot());
this.mBinding = binding;
}
@Override
public void onBind(int position) {
FormEmptyItemViewModel emptyItemViewModel = new FormEmptyItemViewModel(this);
mBinding.setViewModel(emptyItemViewModel);
}
}
/**
* If view type is not handled then show this view
*/
private class UnknownViewHolder extends BaseViewHolder {
UnknownViewHolder(ItemDynamicFormUnknownBinding unknownBinding) {
super(unknownBinding.getRoot());
}
@Override
public void onBind(int position) {
}
}