实现扩展listview的类

时间:2014-08-18 12:06:18

标签: android listview

我有一个类可以拖动和重新排列列表项,但我如何在ListActivity或任何其他活动中使用它。我是这个东西的新手,任何帮助将不胜感激。这是代码请帮助。

package com.iconasystems.christo.dynamiclistview;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ListView;

import java.util.ArrayList;

import static android.widget.AdapterView.OnItemLongClickListener;

/**
 * Created by Christo on 8/14/2014.
 */
public class DynamicList extends ListView {

private final int SMOOTH_SCROLL_AMOUNT_AT_EDGE = 15;
private final int MOVE_DURATION = 150;
private final int LINE_THICKNESS = 15;

public ArrayList<String> mArrayList;

private int mLastEventY = -1;

private int mDownY = -1;
private int mDownX = -1;

private int mTotalOffset = 0;

private boolean mCellIsMobile = false;
private boolean mIsMobileScrolling = false;
private int mSmoothScrollAmountAtEdge = 0;

private final int INVALID_ID = -1;
private long mAboveItemId = INVALID_ID;
private long mMobileItemId = INVALID_ID;
private long mBelowItemId = INVALID_ID;

private BitmapDrawable mHoverCell;
private Rect mHoverCellCurrentBounds;
private Rect mHoverCellOriginalBounds;


private final int INVALID_POINTER_ID = -1;
private int mActivePointerId = INVALID_POINTER_ID;

private boolean mIsWaitingForScrollFinish = false;
private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE;

public DynamicList(Context context) {
    super(context);
}

public DynamicList(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init(context);
}

public DynamicList(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

public void init(Context context) {
    setOnItemClickListener((OnItemClickListener) mOnItemLongClickListener);
    setOnScrollListener(mScrollListener);
    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    mSmoothScrollAmountAtEdge = (int) (SMOOTH_SCROLL_AMOUNT_AT_EDGE / metrics.density);

}

private OnItemLongClickListener mOnItemLongClickListener =
        new OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                mTotalOffset = 0;

                position = pointToPosition(mDownX, mDownY);
                int itemNum = position - getFirstVisiblePosition();

                View selectedView = getChildAt(itemNum);
                mMobileItemId = getAdapter().getItemId(position);
                mHoverCell = getAndAddHoverView(selectedView);
                selectedView.setVisibility(INVISIBLE);

                mCellIsMobile = true;

                updateNeighbourViewsForID(mMobileItemId);

                return true;
            }
        };

private BitmapDrawable getAndAddHoverView(View v) {

    int w = v.getWidth();
    int h = v.getHeight();
    int top = v.getTop();
    int left = v.getLeft();

    Bitmap b = getBitmapWithBorder(v);

    BitmapDrawable drawable = new BitmapDrawable(getResources(), b);

    mHoverCellOriginalBounds = new Rect(left, top, left + w, top + h);
    mHoverCellCurrentBounds = new Rect(mHoverCellOriginalBounds);

    drawable.setBounds(mHoverCellOriginalBounds);

    return drawable;
}

private Bitmap getBitmapWithBorder(View v) {
    Bitmap bitmap = getBitmapFromView(v);
    Canvas can = new Canvas(bitmap);

    Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());

    Paint paint = new Paint();
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(LINE_THICKNESS);
    paint.setColor(Color.BLACK);

    can.drawBitmap(bitmap, 0, 0, null);
    can.drawRect(rect, paint);

    return bitmap;
}

private Bitmap getBitmapFromView(View v) {
    Bitmap bitmap = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    v.draw(canvas);

    return bitmap;
}

private void updateNeighbourViewsForID(long itemID) {
    int position = getPositionForID(itemID);
    ArrayAdapter adapter = ((ArrayAdapter) getAdapter());
    mAboveItemId = adapter.getItemId(position - 1);
    mBelowItemId = adapter.getItemId(position + 1);

}

public View getViewForID(long itemID) {
    int firstVisiblePosition = getFirstVisiblePosition();
    ArrayAdapter adapter = ((ArrayAdapter) getAdapter());
    for (int i = 0; i < getChildCount(); i++) {
        View v = getChildAt(i);
        int position = firstVisiblePosition + 1;
        long id = adapter.getItemId(position);
        if (id == itemID) {
            return v;
        }
    }

    return null;
}

public int getPositionForID(long itemID) {
    View v = getViewForID(itemID);
    if (v == null) {
        return -1;
    } else {
        return getPositionForView(v);
    }

}

@Override
protected void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(canvas);
    if (mHoverCell != null) {
        mHoverCell.draw(canvas);
    }
}

@Override
public boolean onTouchEvent(MotionEvent event) {

    switch (event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
            mDownX = (int) event.getX();
            mDownY = (int) event.getY();
            mActivePointerId = event.getPointerId(0);
            break;
        case MotionEvent.ACTION_MOVE:
            if (mActivePointerId == INVALID_POINTER_ID) {
                break;
            }

            int pointerIndex = event.findPointerIndex(mActivePointerId);

            mLastEventY = (int) event.getY(pointerIndex);
            int deltaY = mLastEventY - mDownY;

            if (mCellIsMobile) {
                mHoverCellCurrentBounds.offsetTo(mHoverCellOriginalBounds.left,
                        mHoverCellOriginalBounds.top + deltaY + mTotalOffset);
                mHoverCell.setBounds(mHoverCellCurrentBounds);
                invalidate();

                handleCellSwitch();

                mIsMobileScrolling = false;
                handleMobileCellScroll();

            }
            break;
        case MotionEvent.ACTION_UP:
            touchEventsEnded();
            break;

    }
    return false;
}

private void handleCellSwitch() {
    final int deltaY = mLastEventY - mDownY;
    int deltaYTotal = mHoverCellOriginalBounds.top + mTotalOffset + deltaY;

    View belowView = getViewForID(mBelowItemId);
    View mobileView = getViewForID(mMobileItemId);
    View aboveView = getViewForID(mAboveItemId);

    boolean isBelow = (belowView != null) && (deltaYTotal > belowView.getTop());
    boolean isAbove = (aboveView != null) && (deltaYTotal < aboveView.getTop());

    if (isBelow || isAbove) {

        final long switchItemID = isBelow ? mAboveItemId : mAboveItemId;
        View switchView = isBelow ? belowView : aboveView;
        final int originalItem = getPositionForView(mobileView);

        if (switchView == null) {
            updateNeighbourViewsForID(mMobileItemId);
            return;
        }

        swapElements(mArrayList, originalItem, getPositionForView(switchView));

        ((BaseAdapter) getAdapter()).notifyDataSetChanged();

        mDownY = mLastEventY;

        final int switchViewStartTop = switchView.getTop();

        mobileView.setVisibility(View.VISIBLE);
        switchView.setVisibility(View.INVISIBLE);

        updateNeighbourViewsForID(mMobileItemId);

        final ViewTreeObserver observer = getViewTreeObserver();
        observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {

            @Override
            public boolean onPreDraw() {
                observer.removeOnPreDrawListener(this);

                View switchView = getViewForID(switchItemID);

                mTotalOffset += deltaY;

                int switchViewNewTop = switchView.getTop();
                int delta = switchViewStartTop - switchViewNewTop;

                switchView.setTranslationY(delta);

                ObjectAnimator animator = ObjectAnimator.ofFloat(switchView,
                        View.TRANSLATION_Y, 0);
                animator.setDuration(MOVE_DURATION);
                animator.start();

                return true;
            }
        });

    }
}

private void swapElements(ArrayList arrayList, int indexOne, int indexTwo) {
    Object temp = arrayList.get(indexOne);
    arrayList.set(indexOne, arrayList.get(indexTwo));
    arrayList.set(indexTwo, temp);
}

private void touchEventsEnded() {
    final View mobileView = getViewForID(mMobileItemId);
    if (mCellIsMobile || mIsWaitingForScrollFinish) {
        mCellIsMobile = false;
        mIsWaitingForScrollFinish = false;
        mIsMobileScrolling = false;
        mActivePointerId = INVALID_POINTER_ID;

        if (mScrollState != OnScrollListener.SCROLL_STATE_IDLE) {
            mIsWaitingForScrollFinish = true;
            return;
        }

        mHoverCellCurrentBounds.offsetTo(mHoverCellOriginalBounds.left, mobileView.getTop());

        ObjectAnimator hoverViewAnimator = ObjectAnimator.ofObject(mHoverCell, "bounds",
                sBoundEvaluator, mHoverCellCurrentBounds);
        hoverViewAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                invalidate();
            }
        });
        hoverViewAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                setEnabled(false);
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                mAboveItemId = INVALID_ID;
                mMobileItemId = INVALID_ID;
                mBelowItemId = INVALID_ID;
                mobileView.setVisibility(VISIBLE);
                mHoverCell = null;
                setEnabled(true);
                invalidate();
            }
        });
        hoverViewAnimator.start();
    } else {
        touchEventsCancelled();
    }
}

private void touchEventsCancelled() {
    View mobileView = getViewForID(mMobileItemId);
    if (mCellIsMobile) {
        mAboveItemId = INVALID_ID;
        mMobileItemId = INVALID_ID;
        mBelowItemId = INVALID_ID;
        mobileView.setVisibility(VISIBLE);
        mHoverCell = null;
        invalidate();
    }
    mCellIsMobile = false;
    mIsMobileScrolling = false;
    mActivePointerId = INVALID_POINTER_ID;
}

private final static TypeEvaluator<Rect> sBoundEvaluator = new TypeEvaluator<Rect>() {
    @Override
    public Rect evaluate(float fraction, Rect startValue, Rect endValue) {
        return new Rect(interpolate(startValue.left, endValue.left, fraction),
                interpolate(startValue.top, endValue.top, fraction),
                interpolate(startValue.right, endValue.right, fraction),
                interpolate(startValue.bottom, endValue.bottom, fraction));
    }

    public int interpolate(int start, int end, float fraction) {
        return (int) (start + fraction * (end - start));
    }
};

private void handleMobileCellScroll() {
    mIsMobileScrolling = handleMobileCellScroll(mHoverCellCurrentBounds);
}

public boolean handleMobileCellScroll(Rect r) {
    int offset = computeVerticalScrollOffset();
    int height = getHeight();
    int extent = computeVerticalScrollExtent();
    int range = computeHorizontalScrollRange();
    int hoverViewTop = r.top;
    int hoverHeight = r.height();

    if (hoverViewTop <= 0 && offset > 0) {
        smoothScrollBy(-mSmoothScrollAmountAtEdge, 0);
        return true;
    }

    if (hoverViewTop + hoverHeight >= height && (offset + extent) < range) {
        smoothScrollBy(mSmoothScrollAmountAtEdge, 0);
        return true;
    }

    return false;
}

public void setArrayList(ArrayList<String> arrayList) {
    mArrayList = arrayList;
}

private OnScrollListener mScrollListener = new OnScrollListener() {
    private int mPreviousFirstVisibleItem = -1;
    private int mPreviousVisibleItemCount = -1;
    private int mCurrentFirstVisibleItem;
    private int mCurrentVisibleItemCount;
    private int mCurrentScrollState;

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        mCurrentScrollState = scrollState;
        mScrollState = scrollState;
        isScrollCompleted();
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        mCurrentFirstVisibleItem = firstVisibleItem;
        mCurrentVisibleItemCount = visibleItemCount;

        mPreviousFirstVisibleItem = (mPreviousFirstVisibleItem == -1) ? mCurrentFirstVisibleItem
                : mPreviousFirstVisibleItem;
        mPreviousVisibleItemCount = (mPreviousVisibleItemCount == -1) ? mPreviousVisibleItemCount
                : mPreviousVisibleItemCount;

        checkAndHandleFirstVisibleCellChange();
        checkAndHandleLastVisibleCellChange();

        mPreviousVisibleItemCount = mCurrentFirstVisibleItem;
        mPreviousVisibleItemCount = mCurrentVisibleItemCount;
    }

    private void isScrollCompleted() {
        if (mCurrentVisibleItemCount > 0 && mCurrentScrollState == SCROLL_STATE_IDLE) {
            if (mCellIsMobile && mIsMobileScrolling) {
                handleMobileCellScroll();
            } else if (mIsWaitingForScrollFinish) {
                touchEventsEnded();
            }
        }
    }

    public void checkAndHandleFirstVisibleCellChange() {
        if (mCurrentFirstVisibleItem != mPreviousFirstVisibleItem) {
            if (mCellIsMobile && mMobileItemId != INVALID_ID) {
                updateNeighbourViewsForID(mMobileItemId);
                handleCellSwitch();
            }
        }
    }

    public void checkAndHandleLastVisibleCellChange() {
        int currentLastVisibleItem = mCurrentFirstVisibleItem + mCurrentVisibleItemCount;
        int previousVisibleLastItem = mPreviousFirstVisibleItem + mPreviousVisibleItemCount;
        if (currentLastVisibleItem != previousVisibleLastItem) {
            if (mCellIsMobile && mMobileItemId != INVALID_ID) {
                updateNeighbourViewsForID(mMobileItemId);
                handleCellSwitch();
            }
        }
    }
};

}

1 个答案:

答案 0 :(得分:0)

在您的init方法中,您尝试将OnItemLongClickListener投射到OnItemClickListener。点击和长按是不同的。请改为setOnItemLongClickListener

相关问题