赞
踩
其效果如下图:
拖动排序在RecyclerView有现成的解决方案,配合ItemTouchHelper即可轻松实现。但是要将一个列表中的Item拖动到另一个列表中去,就不那么容易了。
先来看看这种跨界面实现由那些难点,我们先分析,再一个一个的解决。
现在我们来一个一个的解决上面的问题:
1. 对于第一个问题,解决方法是当判断Item被长按后,将当前Item记录为一张图片,然后设置给一个隐藏的ImageView,对这个ImageView做Translate平移。这里需要额外费心的是这个ImageView与长按Item视图的重合以及显隐判断。
2. 如果使用ViewPager,由于要跨越两个page,那么触摸事件,保存的图片等都要交给其父控制器,还不如自定义一个ViewGroup。
3. 由于系统提供了在一个RecyclerView中拖动的Helper类,我们无需去解决拖动的起始位置这些,那何乐不为呢?所以,跨界面拖动用自己的实现。
4. 触摸point信息的获取:dispatchTouchEvent方法是最先到的,在我们自定义的ViewPager中重写该方法。在adapter中对itemview添加手势监听,获取到被长按的View。
(1) 自定义的父视图:
public class NewLinearLayout extends LinearLayout {
/*将触摸点坐标传递出去*/
private IGetX iGetX;
/*弹性滑动*/
private Scroller mScroller;
public NewLinearLayout(Context context) {
super(context);
init(context);
}
public NewLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public NewLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
/*initial*/
public void init(Context context){
mScroller = new Scroller(context);
}
@Override
public void computeScroll(){
super.computeScroll();
/*判断是否完成滑动*/
if(mScroller.computeScrollOffset()){
scrollTo(mScroller.getCurrX() , 0);
/*循环调用该方法*/
postInvalidate();
}
}
/*开启弹性滑动*/
public void beginScroll(int dx ){
mScroller.startScroll(mScroller.getCurrX() , 0 , dx , 0 , 1000);
/*调用computeScroll()方法*/
invalidate();
}
@Override
public boolean dispatchTouchEvent(MotionEvent event){
float dx = event.getX();
float dy = event.getY();
if(event.getAction() == MotionEvent.ACTION_MOVE)
iGetX.point(dx , dy);
return super.dispatchTouchEvent(event);
}
public void set(IGetX iGetX){
this.iGetX = iGetX;
}
public interface IGetX{
void point(float dx , float dy);
}
}

(2) View转bitmap
public Bitmap view2bitmap(View view) {
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
view.draw(new Canvas(bitmap));
return bitmap;
}
(3) Adapter的实现
private class Recycler1Adapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private ArrayList<String> mData;
public void setData(ArrayList<String> mData) {
this.mData = mData;
}
public void addData(ArrayList<String> mData) {
this.mData.addAll(mData);
notifyDataSetChanged();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(SpanDragActivity.this).inflate(R.layout.item_launch_title, null);
final Recycler1ViewHolder viewHolder = new Recycler1ViewHolder(itemView);
viewHolder.itemView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
mDetector.onTouchEvent(event);
if(event.getAction() == MotionEvent.ACTION_DOWN){
bitmap = null;
TempItemView = viewHolder.itemView;
startX = TempItemView.getLeft();
startY = TempItemView.getTop();
}
/*恢复计点*/
if(event.getAction() == MotionEvent.ACTION_UP){
isFirstPoint = true;
}
return false;
}
});
return viewHolder;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((Recycler1ViewHolder) holder).mTv.setText(mData.get(position));
}
@Override
public int getItemCount() {
return mData.size();
}
/*create viewholder*/
class Recycler1ViewHolder extends RecyclerView.ViewHolder {
private TextView mTv;
public Recycler1ViewHolder(View itemView) {
super(itemView);
mTv = (TextView) itemView.findViewById(R.id.item_launch_title_tv_title);
}
}
}

(4) 滑动到边缘后触发的事件
/*设置接口获取手指位置*/
activitySpanLl.set(new NewLinearLayout.IGetX() {
@Override
public void point(float dx , float dy) {
Log.v("out", "手指位置:" + dx);
if(isFirstPoint){
firstX = dx;
firstY = dy;
isFirstPoint = false;
}
if(bitmap != null) {
activitySpanImg.setTranslationX(dx-firstX+startX);
activitySpanImg.setTranslationY(dy-firstY+startY);
}
if(dx >=800){
}
if (isFirstScroll)
if (dx >= 1000) {
activitySpanLl.beginScroll(1080);
isFirstScroll = false;
/*向右边滑动了,所以现在可以向左滑动了*/
isFirstLeftScroll = true;
int a = activitySpanLl.getScrollX();
float b = activitySpanLl.getX();
}
if(isFirstLeftScroll)
if(dx <= 80){
activitySpanLl.beginScroll(-1080);
isFirstLeftScroll = false;
/*向左边滑动了,所以现在可以向右滑动了*/
isFirstScroll = true;
int a = activitySpanLl.getScrollX();
float b = activitySpanLl.getX();
}
}
});

有更多问题留言交流。
注意:
因为电脑更换,本demo源码已经找不到了,但是鉴于很多人需要,所以这周我重新写一个demo,需要的先加这个QQ群(之前由于一些原因博客停止更新,接下来会继续更新,主要是音视频相关的,也可以入群交流)
703660703
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。