系统桌面的图标是可以拖拽,大家用起来好像也很习惯。不知道从什么时候开始,应用中的gridview也常常被人拿来做类似的效果。像支付宝,uc,还有一些新闻类的app都有拖拽控件的效果。对于item数量比较多的情况使用拖拽控件是一个比较不错的选择。
然后客户就开始想象自己有很多很多的类似小功能,然后就出现了这篇blog。
虽然只有十个不到的功能按钮,然而我们要有雄伟的蓝图,以后我们会有好多好多的功能的。用户使用的时候就会觉得不方便的。我们需要把按钮的排序权利交给用户。然后我们还要展开收缩的功能。为了界面的整洁美观,一行就放5个按钮,第一行的第五个按钮就是更多按钮,这是用来展开收拢的。按钮全部来自网络,我们需要随时更新的。
其实拖拽还是简单的,展开收拢也没什么难度。然而为什么要让第五个按钮成为更多呢?!?!?!?!?瞬间日子就很难过了。
有一个失败的例子就是继承自gridview的拖拽控件,动画效果十分生硬,还有各种闪烁的情况。想想网上的大神们应该没有写过这一类的帅气的空间吧。
感谢 http://blog.csdn.net/sk719887916/article/details/40074663 博主 为我提供了这个帅帅拖拽基础控件。
package com.kting.baijinka.util;
/*
import java.util.ArrayList;
import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.VelocityTrackerCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewConfigurationCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.animation.AlphaAnimation;
import android.view.animation.AnimationSet;
import android.view.animation.Interpolator;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.Adapter;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.Scroller;
import com.kting.baijinka.adapter.ICBCButtonAdapter;
/**
* Zaker style grid view pager, support dragging & rearrange, using as zaker's main screen.
*/
public class DraggableGridViewPager extends ViewGroup {
private static final String TAG = "DraggableGridViewPager";
private static final boolean DEBUG = true;
private static final boolean USE_CACHE = false;
private static void DEBUG_LOG(String msg) {
if (DEBUG) {
Log.v(TAG, msg);
}
}
// layout
private static final int DEFAULT_COL_COUNT = 5;
private static final int DEFAULT_ROW_COUNT = 12;
private static final int DEFAULT_GRID_GAP = 2; // gap between grids (dips)
private static final int MAX_SETTLE_DURATION = 600; // ms
private static final int MIN_DISTANCE_FOR_FLING = 25; // dips
private static final int MIN_FLING_VELOCITY = 600; // dips
private static final int CLOSE_ENOUGH = 5; // dp
private static final Interpolator sInterpolator = new Interpolator() {
public float getInterpolation(float t) {
t -= 1.0f;
return t * t * t * t * t + 1.0f;
}
};
private static final int INVALID_POINTER = -1;
public static final int SCROLL_STATE_IDLE = 0;
public static final int SCROLL_STATE_DRAGGING = 1;
public static final int SCROLL_STATE_SETTLING = 2;
private static final long LONG_CLICK_DURATION = 500; // ms
private static final long ANIMATION_DURATION = 150; // ms
private static final int EDGE_LFET = 0;
private static final int EDGE_RIGHT = 1;
private static final long EDGE_HOLD_DURATION = 1200; // ms
private int mColCount = DEFAULT_COL_COUNT;
private int mRowCount = DEFAULT_ROW_COUNT;
private int mPageSize = mColCount * mRowCount;
private int mGridGap;
private int mPageCount;
private int mGridWidth;
private int mGridHeight;
private int mMaxOverScrollSize;
private int mEdgeSize;
// internal paddings
private int mPaddingLeft;
private int mPaddingTop;
private int mPaddingRight;
private int mPaddingButtom;
private int mCurItem; // Index of currently displayed page.
private Adapter mAdapter;
private final DataSetObserver mDataSetObserver = new DataSetObserver() {
@Override
public void onChanged() {
dataSetChanged();
}
@Override
public void onInvalidated() {
dataSetChanged();
}
};
private Scroller mScroller;
private boolean mScrollingCacheEnabled;
private boolean mIsBeingDragged;
private boolean mIsUnableToDrag;
private int mTouchSlop;
private float mLastMotionX;
private float mLastMotionY;
private float mInitialMotionX;
private float mInitialMotionY;
private int mActivePointerId = INVALID_POINTER;
private VelocityTracker mVelocityTracker;
private int mMinimumVelocity;
private int mMaximumVelocity;
private int mFlingDistance;
private int mCloseEnough;
// click & long click
private int mLastPosition = -1;
private long mLastDownTime = Long.MAX_VALUE;
// rearrange
private int mLastDragged = -1;
private int mLastTarget = -1;
// edge holding
private int mLastEdge = -1;
private long mLastEdgeTime = Long.MAX_VALUE;
private ArrayList<Integer> newPositions = new ArrayList<Integer>();
private boolean mCalledSuper;
private OnPageChangeListener mOnPageChangeListener;
private OnItemClickListener mOnItemClickListener;
private OnItemLongClickListener mOnItemLongClickListener;
private OnRearrangeListener mOnRearrangeListener;
private final Runnable mEndScrollRunnable = new Runnable() {
public void run() {
setScrollState(SCROLL_STATE_IDLE);
}
};
private int mScrollState = SCROLL_STATE_IDLE;
/**
* Callback interface for responding to changing state of the selected page.
*/
public interface OnPageChangeListener {
/**
* This method will be invoked when the current page is scrolled, either as part of a programmatically initiated
* smooth scroll or a user initiated touch scroll.
*
* @param position
* Position index of the first page currently being displayed. Page position+1 will be visible if
* positionOffset is nonzero.
* @param positionOffset
* Value from [0, 1) indicating the offset from the page at position.
* @param positionOffsetPixels
* Value in pixels indicating the offset from position.
*/
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);
/**
* This method will be invoked when a new page becomes selected. Animation is not necessarily complete.
*
* @param position
* Position index of the new selected page.
*/
public void onPageSelected(int position);
/**
* Called when the scroll state changes. Useful for discovering when the user begins dragging, when the pager is
* automatically settling to the current page, or when it is fully stopped/idle.
*
* @param state
* The new scroll state.
* @see DraggableGridViewPager#SCROLL_STATE_IDLE
* @see DraggableGridViewPager#SCROLL_STATE_DRAGGING
* @see DraggableGridViewPager#SCROLL_STATE_SETTLING
*/
public void onPageScrollStateChanged(int state);
}
/**
* Simple implementation of the {@link OnPageChangeListener} interface with stub implementations of each method.
* Extend this if you do not intend to override every method of {@link OnPageChangeListener}.
*/
public static class SimpleOnPageChangeListener implements OnPageChangeListener {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// This space for rent
}
@Override
public void onPageSelected(int position) {
// This space for rent
}
@Override
public void onPageScrollStateChanged(int state) {
// This space for rent
}
}
public interface OnRearrangeListener {
public abstract void onRearrange(int oldIndex, int newIndex);
}
public DraggableGridViewPager(Context context) {
super(context);
initDraggableGridViewPager();
}
public DraggableGridViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
initDraggableGridViewPager();
}
public DraggableGridViewPager(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initDraggableGridViewPager();
}
private void initDraggableGridViewPager() {
setWillNotDraw(false);
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
setFocusable(true);
setChildrenDrawingOrderEnabled(true);
final Context context = getContext();
final ViewConfiguration configuration = ViewConfiguration.get(context);
final float density = context.getResources().getDisplayMetrics().density;
mGridGap = (int) (DEFAULT_GRID_GAP * density);
// internal paddings
mPaddingLeft = getPaddingLeft();
mPaddingTop = getPaddingTop();
mPaddingRight = getPaddingRight();
mPaddingButtom = getPaddingBottom();
super.setPadding(0, 0, 0, 0);
mScroller = new Scroller(context, sInterpolator);
mTouchSlop = ViewCo