RecyclerView长拖动拖动以重新排序摆动效果

时间:2018-02-14 15:24:48

标签: android animation android-recyclerview drag-and-drop android-animation

当使用GridLayoutManager长时间点击RecyclerView中的项目并拖动重新排序时,如何实现像this这样的摆动效果,哪种工作正常。当放下项目时,效果应该停止。

这是我的Adapter类

public class ClassGridAdapter extends RecyclerView.Adapter<ClusterGridAdapter.ViewHolder> implements ItemTouchHelperCluster {
private ArrayList<Class> mClassList = new ArrayList<>();
private Context mContext;

public ClassGridAdapter(Context context, ArrayList<Class> mClusters) {
    this.mClassList = mClusters;
    this.mContext = context;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(mContext);
    View view = inflater.inflate(R.layout.grid_item, parent, false);
    return new ViewHolder(view);
}

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
    holder.mClusterName.setText(mClassList.get(position).getName());
    holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View view) {
            mDragStartListener.onStartDrag(holder);
            return true;
        }
    });
}

@Override
public int getItemCount() {
    return mClusters.size();
}

@Override
public boolean onItemMove(int fromPosition, int toPosition) {
    Collections.swap(mClassList, fromPosition, toPosition);
    notifyItemMoved(fromPosition, toPosition);
    return true;
}

class ViewHolder extends RecyclerView.ViewHolder {
    TextView mClusterName;
    public ViewHolder(View itemView) {
        super(itemView);
        mClusterName = (TextView) itemView.findViewById(R.id.tv_cluster);
    }
}

}

2 个答案:

答案 0 :(得分:2)

通过在@Cheticamp帮助下执行代码来管理修复它。

ClassGridAdapter.java

public class ClassGridAdapter extends RecyclerView.Adapter<ClusterGridAdapter.ViewHolder> implements ItemTouchHelperCluster {
private ArrayList<Class> mClassList = new ArrayList<>();
private Context mContext;
boolean isAnimate = false;
Animation animation;

public ClassGridAdapter(Context context, ArrayList<Class> mClusters) {
    this.mClassList = mClusters;
    this.mContext = context;
    animation = AnimationUtils.loadAnimation(mContext, R.anim.wobble);
    setHasStableIds(true);
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(mContext);
    View view = inflater.inflate(R.layout.grid_item, parent, false);
    return new ViewHolder(view);
}

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
    holder.mClusterName.setText(mClassList.get(position).getName());
    if (isAnimate)
        holder.itemView.startAnimation(animation);
    else
        holder.itemView.clearAnimation();
    holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View view) {
            mDragStartListener.onStartDrag(holder);
            isAnimate = true;
            notifyDataSetChanged();
            return true;
        }
    });
}

@Override
public int getItemCount() {
    return mClusters.size();
}

@Override
public boolean onItemMove(int fromPosition, int toPosition) {
    Collections.swap(mClassList, fromPosition, toPosition);
    notifyItemMoved(fromPosition, toPosition);
    return true;
}

@Override
public void onItemRelease() {
    isAnimate = false;
    notifyDataSetChanged();
}

class ViewHolder extends RecyclerView.ViewHolder {
    TextView mClusterName;
    public ViewHolder(View itemView) {
        super(itemView);
        mClusterName = (TextView) itemView.findViewById(R.id.tv_cluster);
    }
}

}

wobble.xml

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="100"
android:fromDegrees="-5"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:toDegrees="5" />

SimpleItemTouchHelperCallback.java

public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {

public static final float ALPHA_FULL = 1.0f;

private final ItemTouchHelperCluster mAdapter;

public SimpleItemTouchHelperCallback(ItemTouchHelperCluster adapter) {
    mAdapter = adapter;
}

@Override
public boolean isLongPressDragEnabled() {
    return false;
}

@Override
public boolean isItemViewSwipeEnabled() {
    return false;
}

@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    // Set movement flags based on the layout manager
    if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {
        final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
        final int swipeFlags = 0;
        return makeMovementFlags(dragFlags, swipeFlags);
    } else {
        final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
        return makeMovementFlags(dragFlags, swipeFlags);
    }
}

@Override
public boolean onMove(RecyclerView recyclerView, 
 RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) {
    System.out.println("SimpleItemTouchHelperCallback.onMove");
    if (source.getItemViewType() != target.getItemViewType()) {
        return false;
    }

    // Notify the adapter of the move
    mAdapter.onItemMove(source.getAdapterPosition(), 
target.getAdapterPosition());
    return true;
}

@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int i) {
    System.out.println("SimpleItemTouchHelperCallback.onSwiped");
    // Notify the adapter of the dismissal
    //        mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
}

@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
    if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
        // Fade out the view as it is swiped out of the parent's bounds
        final float alpha = ALPHA_FULL - Math.abs(dX) / (float) v . 
 iewHolder.itemView.getWidth();
        viewHolder.itemView.setAlpha(alpha);
        viewHolder.itemView.setTranslationX(dX);
    } else {
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, 
 actionState, isCurrentlyActive);
    }
}

@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int 
actionState) {
    // We only want the active item to change
    if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
        if (viewHolder instanceof ItemTouchHelperViewHolder) {
            // Let the view holder know that this item is being moved 
 or dragged
            ItemTouchHelperViewHolder itemViewHolder = 
 (ItemTouchHelperViewHolder) viewHolder;
            itemViewHolder.onItemSelected();
        }
    }

    super.onSelectedChanged(viewHolder, actionState);
}

@Override
public void clearView(RecyclerView recyclerView, 
RecyclerView.ViewHolder viewHolder) {
    super.clearView(recyclerView, viewHolder);
    System.out.println("SimpleItemTouchHelperCallback.clearView");
    viewHolder.itemView.setAlpha(ALPHA_FULL);
    mAdapter.onItemRelease();
    if (viewHolder instanceof ItemTouchHelperViewHolder) {
        // Tell the view holder it's time to restore the idle state
        ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
        itemViewHolder.onItemClear();
    }
}
}

答案 1 :(得分:0)

将动画从this answer借用到Stack Overflow上的类似问题,这是如何使四个图像视图的图库摆动,如本视频所示:

enter image description here

此解决方案使用View Animation

对于演示,基于此动画文件使for图像视图振动:

<强> wobble.xml

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="100"
    android:fromDegrees="-5"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="infinite"
    android:repeatMode="reverse"
    android:toDegrees="5" />

这是主要活动。 Wobbling立即开始并在五秒钟后停止。您停止的触发器将是删除视图。

<强> MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.wobble_gallery);
        final int[] ids = new int[]{R.id.imageView1, R.id.imageView2, R.id.imageView3, R.id.imageView4};

        Animation animation = AnimationUtils.loadAnimation(this, R.anim.wobble);
        for (int id : ids) {
            ImageView imageView = (ImageView) findViewById(id);
            imageView.startAnimation(animation);
        }
        findViewById(R.id.imageView1).postDelayed(new Runnable() {
            @Override
            public void run() {
                for (int id : ids) {
                    ImageView imageView = (ImageView) findViewById(id);
                    imageView.clearAnimation();
                }
            }
        }, 5000);
    }
}

最后,布局文件。

<强> wobble_gallery.xml

<GridLayout 
    android:layout_width="match_parent"
    android:layout_gravity="center"
    android:layout_height="match_parent"
    android:columnCount="2">

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="75dp"
        android:layout_height="75dp"
        android:layout_margin="16dp"
        app:srcCompat="@android:drawable/btn_star_big_on" />

    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="75dp"
        android:layout_height="75dp"
        android:layout_margin="16dp"
        app:srcCompat="@drawable/linear_gradient" />

    <ImageView
        android:id="@+id/imageView3"
        android:layout_width="75dp"
        android:layout_height="75dp"
        android:layout_margin="16dp"
        app:srcCompat="@mipmap/ic_launcher_round" />

    <ImageView
        android:id="@+id/imageView4"
        android:layout_width="75dp"
        android:layout_height="75dp"
        android:layout_margin="16dp"
        app:srcCompat="@drawable/dog_image" />
</GridLayout>