我正在尝试在带有modeladapter的列表上使用swipeCallback。为了使其工作,我剥离了所有自定义项并对其进行建模,使其接近示例应用程序,但是这种组合产生了不允许撤消的错误。当我滑动时,会发生这种情况:
滑动有效,但未显示撤消图标。有什么想法我做错了吗?底层片段是这样的:
public class EditFragment extends Fragment implements ItemTouchCallback, SimpleSwipeCallback.ItemSwipeCallback {
private FragmentEditBinding oBinding;
private SongViewModel oViewModel;
//save our FastAdapter
private FastAdapter fastAdapter;
private ModelAdapter<ModelSongCounter, ModelItemView> itemAdapter;
//drag & drop
private SimpleDragCallback touchCallback;
private ItemTouchHelper touchHelper;
public EditFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//init Databinding
oBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_edit, container, false);//.setContentView(getActivity(), R.layout.fragment_main);
//LayoutInflaterCompat.setFactory(getLayoutInflater(), new IconicsLayoutInflater(getActivity()));
//style our ui
new MaterializeBuilder().withActivity(getActivity()).build();
//adapters
//FastScrollIndicatorAdapter fastScrollIndicatorAdapter = new FastScrollIndicatorAdapter();
itemAdapter = new ModelAdapter<>(new IInterceptor<ModelSongCounter, ModelItemView>() {
@Override
public ModelItemView intercept(ModelSongCounter iconModel) {
return new ModelItemView(iconModel);
}
});
//create our FastAdapter which will manage everything
fastAdapter = FastAdapter.with(Arrays.asList(itemAdapter));
fastAdapter.withSelectable(true);
//get our recyclerView and do basic setup
//RecyclerView rv = oBinding.SongRecyclerView;
oBinding.SongRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
//oBinding.SongRecyclerView.setItemAnimator(new SlideDownAlphaAnimator());
oBinding.SongRecyclerView.setAdapter(fastAdapter);
//get ViewModels from Provider
oViewModel = ViewModelProviders.of(getActivity()).get(SongViewModel.class);
//get rid of the annoying blink
oBinding.SongRecyclerView.setItemAnimator(null);
//add Observer to ViewModel
// The onChanged() method fires when the observed data changes and the activity is
// in the foreground.
oViewModel.getAllCatsLive().observe(this, new Observer<List<ModelSongCounter>>() {
@Override
public void onChanged(@Nullable List<ModelSongCounter> modelSongCounters) {
itemAdapter.set(modelSongCounters);
}
});
fastAdapter.withEventHook(new ClickEventHook<ModelItemView>() {
@Nullable
@Override
public View onBind(@NonNull RecyclerView.ViewHolder viewHolder) {
if (viewHolder instanceof ModelItemView.ViewHolder) {
return ((ModelItemView.ViewHolder) viewHolder).Minus;
}
return null;
}
@Override
public void onClick(View v, int position, FastAdapter<ModelItemView> fastAdapter, ModelItemView item) {
//react on the click event
oViewModel.decrement(item.getModel().uid);
}
});
fastAdapter.withEventHook(new ClickEventHook<ModelItemView>() {
@Nullable
@Override
public View onBind(@NonNull RecyclerView.ViewHolder viewHolder) {
if (viewHolder instanceof ModelItemView.ViewHolder) {
return ((ModelItemView.ViewHolder) viewHolder).Plus;
}
return null;
}
@Override
public void onClick(View v, int position, FastAdapter<ModelItemView> fastAdapter, ModelItemView item) {
//react on the click event
oViewModel.increment(item.getModel().uid);
}
});
//restore selections (this has to be done after the items were added
fastAdapter.withSavedInstanceState(savedInstanceState);
//Swipable stuff within OnCreateView
Drawable leaveBehindDrawableLeft = new IconicsDrawable(getContext())
.icon(MaterialDesignIconic.Icon.gmi_delete)
.color(Color.WHITE)
.sizeDp(24);
Drawable leaveBehindDrawableRight = new IconicsDrawable(getContext())
.icon(MaterialDesignIconic.Icon.gmi_archive)
.color(Color.WHITE)
.sizeDp(24);
touchCallback = new SimpleSwipeDragCallback(
this,
this,
leaveBehindDrawableLeft,
ItemTouchHelper.LEFT,
ContextCompat.getColor(getContext(), R.color.md_red_900)
)
.withBackgroundSwipeRight(ContextCompat.getColor(getContext(), R.color.md_blue_900))
.withLeaveBehindSwipeRight(leaveBehindDrawableRight);
touchHelper = new ItemTouchHelper(touchCallback); // Create ItemTouchHelper and pass with parameter the SimpleDragCallback
touchHelper.attachToRecyclerView(oBinding.SongRecyclerView); // Attach ItemTouchHelper to RecyclerView
//restore selections (this has to be done after the items were added
fastAdapter.withSavedInstanceState(savedInstanceState);
return oBinding.getRoot();
}
@Override
public void onSaveInstanceState(Bundle outState) {
//add the values which need to be saved from the adapter to the bundle
outState = fastAdapter.saveInstanceState(outState);
super.onSaveInstanceState(outState);
}
//Swipable...and probably relevant for expandables, since there is TouchOnMove
@Override
public boolean itemTouchOnMove(int oldPosition, int newPosition) {
//DragDropUtil.onMove((ItemAdapter)itemAdapter, oldPosition, newPosition); // change position
return true;
}
@Override
public void itemTouchDropped(int oldPosition, int newPosition) {
//f.e. save new order in database
}
@Override
public void itemSwiped(int position, int direction) {
// -- Option 1: Direct action --
//do something when swiped such as: select, remove, update, ...:
//A) fastItemAdapter.select(position);
//B) fastItemAdapter.remove(position);
//C) update item, set "read" if an email etc
// -- Option 2: Delayed action --
final ModelItemView item = itemAdapter.getAdapterItem(position);
item.setSwipedDirection(direction);
// This can vary depending on direction but remove & archive simulated here both results in
// removal from list
final Runnable removeRunnable = new Runnable() {
@Override
public void run() {
item.setSwipedAction(null);
int position = itemAdapter.getAdapterPosition(item);
if (position != RecyclerView.NO_POSITION) {
//this sample uses a filter. If a filter is used we should use the methods provided by the filter (to make sure filter and normal state is updated)
//fastItemAdapter.getItemFilter().remove(position);
itemAdapter.remove(position);
}
}
};
final View rv = oBinding.SongRecyclerView;
rv.postDelayed(removeRunnable, 3000);
item.setSwipedAction(new Runnable() {
@Override
public void run() {
rv.removeCallbacks(removeRunnable);
item.setSwipedDirection(0);
int position = itemAdapter.getAdapterPosition(item);
if (position != RecyclerView.NO_POSITION) {
fastAdapter.notifyItemChanged(position);
}
}
});
fastAdapter.notifyItemChanged(position);
//TODO can this above be made more generic, along with the support in the item?
}
}
这是可滑动的ModelItem(模型“ ModelSongCounter”只是一个POJO):
public class ModelItemView
extends ModelAbstractItem<ModelSongCounter, ModelItemView, ModelItemView.ViewHolder>
implements ISwipeable<ModelItemView, IItem>, IDraggable<ModelItemView, IItem> {
public StringHolder undoTextSwipeFromLeft;
public int iSwipedDirection;
private Runnable rSwipedAction;
public boolean bSwipable = true;
public boolean draggable = true;
public ModelItemView(ModelSongCounter icon) {
super(icon);
}
/**
* defines the type defining this item. must be unique. preferably an id
*
* @return the type
*/
@Override
public int getType() {
return R.id.iconics_tag_id;
}
/**
* defines the layout which will be used for this item in the list
*
* @return the layout for this item
*/
@Override
public int getLayoutRes() {
return R.layout.item_view;
}
/**
* binds the data of this item onto the viewHolder
*
* @param viewHolder the viewHolder of this item
*/
@Override
public void bindView(ViewHolder viewHolder, List<Object> payloads) {
super.bindView(viewHolder, payloads);
//define our data for the view
viewHolder.name.setText(getModel().getName());
viewHolder.counter.setText(Integer.toString(getModel().getCounter()));
viewHolder.swipeResultContent.setVisibility(iSwipedDirection != 0 ? View.VISIBLE : View.GONE);
viewHolder.itemContent.setVisibility(iSwipedDirection != 0 ? View.GONE : View.VISIBLE);
CharSequence swipedAction = null;
CharSequence swipedText = null;
if(iSwipedDirection != 0){
swipedAction = viewHolder.itemView.getContext().getString(R.string.action_undo);
swipedText = iSwipedDirection == ItemTouchHelper.LEFT ? "Removed" : "Archived - Should not be implemented!";
viewHolder.swipeResultContent.setBackgroundColor(
ContextCompat.getColor(viewHolder.itemView.getContext(),
iSwipedDirection == ItemTouchHelper.LEFT ? R.color.md_red_900 : R.color.md_blue_900));
}
viewHolder.swipedAction.setText(swipedAction == null ? "" : swipedAction);
viewHolder.swipedText.setText(swipedText == null ? "" : swipedText);
viewHolder.rSwipedActionRunnable = this.rSwipedAction;
}
@Override
public void unbindView(ViewHolder holder) {
super.unbindView(holder);
holder.name.setText(null);
holder.counter.setText(null);
holder.swipedAction.setText(null);
holder.swipedText.setText(null);
holder.rSwipedActionRunnable = this.rSwipedAction;
}
@Override
public ViewHolder getViewHolder(View v) {
return new ViewHolder(v);
}
//SWipable
@Override
public boolean isSwipeable() {
return this.bSwipable;
}
@Override
public ModelItemView withIsSwipeable(boolean swipeableP) {
this.bSwipable = swipeableP;
return this;
}
public void setSwipedDirection(int iSwipedDirectionP){
this.iSwipedDirection = iSwipedDirectionP;
}
public void setSwipedAction(Runnable actionP){
this.rSwipedAction = actionP;
}
@Override
public boolean isDraggable() {
return draggable;
}
@Override
public ModelItemView withIsDraggable(boolean draggableP) {
this.draggable = draggableP;
return this;
}
/**
* our ViewHolder
*/
protected static class ViewHolder extends RecyclerView.ViewHolder {
protected View view;
@BindView(R.id.material_drawer_song)
public TextView name;
@BindView(R.id.material_drawer_counter)
public TextView counter;
@BindView(R.id.material_drawer_minus)
public ImageView Minus;
@BindView(R.id.material_drawer_plus)
public ImageView Plus;
@BindView(R.id.swipe_result_content)
public View swipeResultContent;
@BindView(R.id.item_content)
public View itemContent;
@BindView(R.id.swiped_text)
public TextView swipedText;
@BindView(R.id.swiped_action)
public TextView swipedAction;
public Runnable rSwipedActionRunnable;
public ViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
//this.view = view;// ?
swipedAction.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (rSwipedActionRunnable != null){
rSwipedActionRunnable.run();
}
}
});
}
}
}
这是列表项的XML视图:
<?xml version="1.0" encoding="utf-8"?>
<layout>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="@dimen/material_drawer_item_primary">
<LinearLayout
android:id="@+id/swipe_result_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:visibility="visible"
android:paddingEnd="@dimen/material_drawer_vertical_padding"
android:paddingLeft="@dimen/material_drawer_vertical_padding"
android:paddingRight="@dimen/material_drawer_vertical_padding"
android:paddingStart="@dimen/material_drawer_vertical_padding">
<TextView
android:id="@+id/swiped_text"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center_vertical|start"
android:lines="1"
android:singleLine="true"
android:textDirection="anyRtl"
android:textColor="@android:color/primary_text_dark"
android:textSize="@dimen/material_drawer_item_primary_text"
tools:text="Removed"/>
<TextView
android:id="@+id/swiped_action"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:fontFamily="sans-serif"
android:gravity="center_vertical|start"
android:lines="1"
android:singleLine="true"
android:textDirection="anyRtl"
android:textAllCaps="true"
android:textColor="@android:color/primary_text_dark"
android:textStyle="bold"
android:textSize="@dimen/material_drawer_item_primary_description"
android:text="@string/action_undo"/>
</LinearLayout>
<LinearLayout
android:id="@+id/item_content"
android:layout_width="match_parent"
android:layout_height="@dimen/material_drawer_item_primary"
android:orientation="horizontal"
android:paddingEnd="@dimen/material_drawer_vertical_padding"
android:paddingLeft="@dimen/material_drawer_vertical_padding"
android:paddingRight="@dimen/material_drawer_vertical_padding"
android:paddingStart="@dimen/material_drawer_vertical_padding">
<TextView
android:id="@+id/material_drawer_song"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginTop="12dp"
android:layout_marginLeft="12dp"
android:lines="1"
android:singleLine="true"
android:textSize="@dimen/material_drawer_item_primary_text"
tools:text="Some drawer text" />
<TextView
android:id="@+id/material_drawer_counter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginLeft="12dp"
android:fontFamily="sans-serif"
android:lines="1"
android:singleLine="true"
android:textSize="@dimen/material_drawer_item_primary_description"
tools:text="Some counter text"
android:layout_weight="1"
android:gravity="center_vertical|start" />
<ImageView
android:id="@+id/material_drawer_minus"
android:layout_width="50dp"
android:layout_height="match_parent"
app:ico_color="@color/md_black_1000"
app:ico_icon="@string/gmd_remove_circle"
app:ico_size="50dp" />
<ImageView
android:id="@+id/material_drawer_plus"
android:layout_width="50dp"
android:layout_height="match_parent"
app:ico_color="@color/md_black_1000"
app:ico_icon="gmd-add_circle"
app:ico_size="50dp" />
</LinearLayout>
</FrameLayout>
</layout>
答案 0 :(得分:2)
管理undo
按钮显示的代码部分位于bindView()
的{{1}}方法内部。
请确保在刷卡后通过ModelItemView
中的getItem(position)
检索到正确的项目,并确保通过itemSwiped
通知了正确的项目。
此后,确保再次在该元素上触发notifyItemChanged()
,并确保它具有通过bindView()
设置的正确swipeDirection
。
这很重要,因为:
setSwipedDirection(direction)
用于正确调整视图的可见性,包括显示viewHolder.swipeResultContent.setVisibility(iSwipedDirection != 0 ? View.VISIBLE : View.GONE);
viewHolder.itemContent.setVisibility(iSwipedDirection != 0 ? View.GONE : View.VISIBLE);
按钮。
答案 1 :(得分:0)
几个星期后,答案很简单:
撤消按钮取决于itemanimator,为了避免闪烁,我总是将其取消。 Here是一个不错的自定义动画师类,它会覆盖不需要的任何动画。现在我要做的就是
RecyclerView.setItemAnimator(new CustomItemAnimator());