package com.android.Mylauncher2.edit; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import com.android.Mylauncher.R; import com.android.Mylauncher2.Workspace; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.LightingColorFilter; import android.graphics.Paint; import android.graphics.Point; import android.graphics.Rect; import android.graphics.Typeface; import android.graphics.Paint.Style; import android.util.AttributeSet; import android.util.Log; import android.util.SparseArray; import android.util.TypedValue; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; import android.view.View.OnTouchListener; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.RotateAnimation; import android.view.animation.ScaleAnimation; import android.view.animation.TranslateAnimation; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; /** * 页面辑编 * 前当页面是不是可删除用view的id判断,当id > 0时弗成删除,否则是可以删除的,所以在传入view时,要根据是不是可删除设置好id * 用tag记标页面本来的页面索引 * @author wusj * */ public class HomeEditView extends ViewGroup implements OnTouchListener, OnLongClickListener { private static final String TAG = "HomeEditView"; private Context mContext; private Workspace mWorkspace; private List<View> mChilds; // view从一点移到一另点时的平挪动画时长 private static final int ANIMATION_DURATION = 250; // 小于即是4个时的度宽和高度 private static final int SMALL_WIDTH = 300; private static final int SMALL_HEIGHT = 300; // 大于4个页面时,单个页面表现的度宽和高度 private static final int BIG_WIDTH = 100; private static final int BIG_HEIGHT = 140; // 水平两页面之间的间隙 private static final int PAGE_GAP_WIDTH = 5; // 竖直两页面之间的间隙 private static final int PAGE_GAP_HEIGHT = 15; // 删除区域的高度 private static final int DELETE_ZONE_HEIGHT = 40; int dragged = -1; // 前当是不是在挪动view private boolean movingView = false; private int dragLeft; private int dragTop; private TextView add; private boolean isDraggingDefaultPage; public interface OnClickPageListener { public void onClickPage(int index, List<PageInfo> pages); } private OnClickPageListener clickPage; public void setOnClickPageListener(OnClickPageListener listener) { this.clickPage = listener; } private OnClickListener mAddClickListener; public void setAddClickListener(OnClickListener addClickListener) { mAddClickListener = addClickListener; } private OnClickListener onClickListener = new OnClickListener() { @Override public void onClick(View v) { Log.e(TAG, "onClick---v.id is " + v.getId()); if (clickPage != null) { List<PageInfo> pages = getPreviewAllPages(); clickPage.onClickPage(v.getId(), pages); } } }; // 面前是view面后是view地点的置位 private SparseArray<Integer> newPositions = new SparseArray<Integer>(); private int initX; private int initY; private int lastTouchX; private int lastTouchY; private int lastTarget = -1; private Point startPoint; public HomeEditView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public HomeEditView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.mContext = context; setOnTouchListener(this); setOnLongClickListener(this); } public void initWorkspace(Workspace workspace) { mWorkspace = workspace; } /** * when customer click add button * @param view * @param i */ public void addOnePage(View view, int i) { addView(view, i); //view.setTag(i); newPositions.put(i, i); } /** * create the previews according to all CellLayouts existed now * @param views all previews created from CellLayout */ public void addExistedPages(List<View> views) { removeAllViews(); for (int i = 0; i < views.size(); i++) { View view = views.get(i); addView(view); view.setTag(i); newPositions.put(i, i); } //create ADD page if (views.size() <= 8) { addView(createAddView()); } } @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: initX = (int) event.getX(); initY = (int) event.getY(); int target = getTargetAtCoor(initX, initY); if(target == mWorkspace.getDefaultHomePage()) { isDraggingDefaultPage = true; } lastTouchX = (int) event.getX(); lastTouchY = (int) event.getY(); break; case MotionEvent.ACTION_MOVE: eventMove(event); break; case MotionEvent.ACTION_UP: touchUp(event); break; default: break; } if (aViewIsDragged()) { return true; } return false; } private void touchUp(MotionEvent event) { if (!aViewIsDragged()) { if (onClickListener != null) { View clickedView = getChildAt(getTargetAtCoor((int) event.getX(), (int) event.getY())); Log.e(TAG, "clickedView : " + clickedView); if(clickedView != null) onClickListener.onClick(clickedView); } } else { Log.e(TAG, "touchUp---lastTarget is " + lastTarget); //hideDeleteView(); manageChildrenReordering(); movingView = false; dragged = -1; if(isDraggingDefaultPage){ mWorkspace.setDefaultHomePage(lastTarget); } lastTarget = -1; cancelAnimations(); } } private void cancelAnimations() { for (int i = 0; i < getChildCount(); i++) { if (i != dragged) { View child = getChildAt(i); child.clearAnimation(); } } } private void manageChildrenReordering() { /*boolean draggedDeleted = touchUpInDeleteZoneDrop(lastTouchX, lastTouchY); Log.e(TAG, "the draggedDeleted is " + draggedDeleted); if (draggedDeleted) { View view = getChildAt(dragged); int id = view.getId(); Log.e(TAG, "id : " + id); } if (draggedDeleted) { animateDeleteDragged(); reorderChildrenWhenDraggedIsDeleted(); } else { reorderChildren(); }*/ reorderChildren(); } // 当有页面被删除时,重新排列view private void reorderChildrenWhenDraggedIsDeleted() { Integer newDraggedPosition = newPositions.get(dragged,dragged); List<View> children = cleanUnorderedChildren(); addReorderedChildrenToParent(children); // tellAdapterDraggedIsDeleted(newDraggedPosition); removeViewAt(newDraggedPosition); if (add != null && add.getParent() != this) { addView(createAddView(), getChildCount() - 1); } requestLayout(); } // 删除时的缩小动画 private void animateDeleteDragged() { ScaleAnimation scale = new ScaleAnimation(1.4f, 0f, 1.4f, 0f);//, biggestChildWidth / 2 , biggestChildHeight / 2); scale.setDuration(200); scale.setFillAfter(true); scale.setFillEnabled(true); getChildAt(dragged).clearAnimation(); getChildAt(dragged).startAnimation(scale); } private void reorderChildren() { Log.e(TAG, "reorderChildren()"); List<View> children = cleanUnorderedChildren(); addReorderedChildrenToParent(children); requestLayout(); } private void removeItemChildren(List<View> children) { for (View child : children) { removeView(child); } } private List<View> cleanUnorderedChildren() { List<View> children = saveChildren(); removeItemChildren(children); return children; } private void addReorderedChildrenToParent(List<View> children) { List<View> reorderedViews = reeorderView(children); newPositions.clear(); for (View view : reorderedViews) { if (view != null) addView(view); } } // 重新排列view private List<View> reeorderView(List<View> children) { Log.e(TAG, "reeorderView()"); View[] views = new View[children.size()]; for (int i = 0; i < children.size(); i++) { int position = newPositions.get(i, -1); Log.e(TAG, "the position is " + position); if (position != -1) { views[position] = children.get(i); } else { views[i] = children.get(i); } } return new ArrayList<View>(Arrays.asList(views)); } // 将view存保返回 private List<View> saveChildren() { List<View> children = new ArrayList<View>(); for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); child.clearAnimation(); children.add(child); } return children; } private void eventMove(MotionEvent event) { if (movingView && aViewIsDragged()) { lastTouchX = (int) event.getX(); lastTouchY = (int) event.getY(); moveDraggedView(lastTouchX, lastTouchY); manageSwapPosition(lastTouchX, lastTouchY); //manageDeleteZoneHover(lastTouchX, lastTouchY); } } // 挪动时的置位换交管理 private void manageSwapPosition(int x, int y) { int target = getTargetAtCoor(x, y); Log.e(TAG, "target : " + target); if (target != -1 && target != lastTarget) { animateGap(target); lastTarget = target; } } // 通过面后的置位(value),失掉面前的view(key) private int currentViewAtPosition(int targetLocation) { int viewAtPosition = targetLocation; for (int i = 0; i < newPositions.size(); i++) { int value = newPositions.valueAt(i); if (value == targetLocation) { viewAtPosition = newPositions.keyAt(i); break; } } return viewAtPosition; } private void animateGap(int target) { Log.e(TAG, "animateGap()---the target is " + target); int viewAtPosition = currentViewAtPosition(target); if (getChildAt(viewAtPosition) == add) { return; } // 源始置位 View origin = getChildAt(viewAtPosition); Log.e(TAG, "the origin.getid is " + origin.getId()); int originLeft = origin.getLeft(); int originTop = origin.getTop(); if (viewAtPosition == dragged) { originLeft = dragLeft; originTop = dragTop; } // 前当置位 View curr = getChildAt(target); Log.e(TAG, "the curr.getid is " + curr.getId()); int currLeft = curr.getLeft(); int currTop = curr.getTop(); if (target == dragged) { currLeft = dragLeft; currTop = dragTop; } // 将要到达置位 View tar = getChildAt(newPositions.get(dragged, dragged)); Log.e(TAG, "the tar.getid is " + tar.getId()); int tarLeft = tar.getLeft(); int tarTop = tar.getTop(); if (newPositions.get(dragged, dragged) == dragged) { tarLeft = dragLeft; tarTop = dragTop; } Point oldOffset = new Point(); oldOffset.x = currLeft - originLeft; oldOffset.y = currTop - originTop; Point newOffset = new Point(); newOffset.x = tarLeft - originLeft; newOffset.y = tarTop - originTop; animateMoveToNewPosition(getChildAt(viewAtPosition), oldOffset, newOffset); saveNewPosition(target, viewAtPosition); } private void saveNewPosition(int target, int viewInTarget) { newPositions.put(viewInTarget, newPositions.get(dragged, dragged)); newPositions.put(dragged, target); } // 获得指定点上的view的索引 private int getTargetAtCoor(int x, int y) { int ret = -1; // 减1明说:最后的deleteZone for (int i = 0; i < getChildCount() - 1; i++) { View child = getChildAt(i); if (child == getChildAt(dragged)) { // if (dragged != i) int count = getChildCount(); if (count < 5) { if ((x > dragLeft && x < dragLeft + SMALL_WIDTH) && (y > dragTop && y < dragTop + SMALL_HEIGHT)) { return i; } } else { if ((x > dragLeft && x < dragLeft + BIG_WIDTH) && (y > dragTop && y < dragTop + BIG_HEIGHT)) { return i; } } continue; } if (isPointInsideView(x, y, child)) { return i; } } return ret; } // 挪动被拖曳的view private void moveDraggedView(int x, int y) { View childAt = getChildAt(dragged); int width = childAt.getMeasuredWidth(); int height = childAt.getMeasuredHeight(); int l = x - (1 * width / 2); int t = y - (1 * height / 2); childAt.layout(l, t, l + width, t + height); } // 调整view的巨细 private void updateSize() { int count = getChildCount() - 1; if (count < 5) { for (int i = 0; i < count; i++) { View view = getChildAt(i); float wid = view.getWidth(); float hei = view.getHeight(); view.setScaleX(SMALL_WIDTH / wid); view.setScaleY(SMALL_HEIGHT / hei); } } else { for (int i = 0; i < count; i++) { View view = getChildAt(i); float wid = view.getWidth(); float hei = view.getHeight(); view.setScaleX(BIG_WIDTH / wid); view.setScaleY(BIG_HEIGHT / hei); } } } //mcoy 获取preview界面上所有的pages public List<PageInfo> getPreviewAllPages() { List<PageInfo> pages = new ArrayList<PageInfo>(); for (int i = 0; i < getChildCount() - 1; i++) { View child = getChildAt(i); if (child == add) { continue; } PageInfo info = new PageInfo(); info.originPage = (Integer) child.getTag(); Log.e(TAG, "tag : " + info.originPage); info.currentPage = i; pages.add(info); } return pages; } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int count = getChildCount(); // updateSize(); Log.e(TAG, "count is " + count); int left1 = getWidth() / 2 - (BIG_WIDTH * 3 + 2 * PAGE_GAP_WIDTH) / 2; int left2 = left1; int left3 = left1; for (int i = 0; i < count; i++) { View child = getChildAt(i); //mcoy after we clicking one page, we turn to the appropriat page according to the id child.setId(i); if (child.getVisibility() == View.GONE) { continue; } if (i < 3) { child.layout(left1, DELETE_ZONE_HEIGHT, left1 + BIG_WIDTH, BIG_HEIGHT + DELETE_ZONE_HEIGHT); left1 += BIG_WIDTH + PAGE_GAP_WIDTH; } else if (i >= 3 && i <= 5) { child.layout(left2, BIG_HEIGHT + PAGE_GAP_HEIGHT + DELETE_ZONE_HEIGHT, left2 + BIG_WIDTH, BIG_HEIGHT * 2 + PAGE_GAP_HEIGHT + DELETE_ZONE_HEIGHT); left2 += BIG_WIDTH + PAGE_GAP_WIDTH; } else { child.layout(left3, BIG_HEIGHT * 2 + PAGE_GAP_HEIGHT * 2 + DELETE_ZONE_HEIGHT, left3 + BIG_WIDTH, BIG_HEIGHT * 2 + PAGE_GAP_HEIGHT * 2 + BIG_HEIGHT + DELETE_ZONE_HEIGHT); left3 += BIG_WIDTH + PAGE_GAP_WIDTH; } } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { Log.e(TAG, "onMeasure"); super.onMeasure(widthMeasureSpec, heightMeasureSpec); int count = getChildCount(); if (count < 5) { for (int i = 0; i < count; i++) { View child = getChildAt(i); child.measure(MeasureSpec.makeMeasureSpec(SMALL_WIDTH, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec( SMALL_HEIGHT, MeasureSpec.EXACTLY)); } } else { for (int i = 0; i < count; i++) { View child = getChildAt(i); child.measure(MeasureSpec.makeMeasureSpec(BIG_WIDTH, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec( BIG_HEIGHT, MeasureSpec.EXACTLY)); } } } private float getPixelFromDip(int size) { Resources r = getResources(); float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size, r.getDisplayMetrics()); return px; } @Override public boolean onLongClick(View v) { Log.e(TAG, "onLongClick()"); if ((dragged = positionForView()) != -1) { if (getChildAt(dragged) == add) { // 长按的是添加按钮不造成移动事件 return true; } startPoint = new Point(); // getLeft()和getTop()取对相父控件的距离 dragLeft = (int) getChildAt(dragged).getLeft(); dragTop = (int) getChildAt(dragged).getTop(); movingView = true; animateMoveAllItems(); animateDragged(); //popDeleteView(); return true; } return false; } // 长按时,判断前当按下的是不是一个页面 private int positionForView() { for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); if (isPointInsideView(initX, initY, child)) { return i; } } return -1; } // 判断按下的点是不是在view上 private boolean isPointInsideView(float x, float y, View view) { int viewX = view.getLeft(); int viewY = view.getTop(); if (pointIsInsideViewBounds(x, y, view, viewX, viewY)) { return true; } else { return false; } } private boolean pointIsInsideViewBounds(float x, float y, View view, int viewX, int viewY) { return (x > viewX && x < (viewX + view.getWidth())) && (y > viewY && y < (viewY + view.getHeight())); } // 动启其它页面的跳动动画 private void animateMoveAllItems() { Animation rotateAnimation = createFastRotateAnimation(); for (int i = 0; i < getChildCount() - 1; i++) { View child = getChildAt(i); child.startAnimation(rotateAnimation); } } // 拖拽时其它页面的跳动动画 private Animation createFastRotateAnimation() { Animation rotate = new RotateAnimation(-2.0f, 2.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotate.setRepeatMode(Animation.REVERSE); rotate.setRepeatCount(Animation.INFINITE); rotate.setDuration(60); rotate.setInterpolator(new AccelerateDecelerateInterpolator()); return rotate; } // 给被拖曳的item加放大动画 private void animateDragged() { ScaleAnimation scale = new ScaleAnimation(1f, 1.4f, 1f, 1.4f);// , // biggestChildWidth // / 2 , // biggestChildHeight // / 2); scale.setDuration(200); scale.setFillAfter(true); scale.setFillEnabled(true); if (aViewIsDragged()) { getChildAt(dragged).clearAnimation(); getChildAt(dragged).startAnimation(scale); } } // old动画起始点对相view的距离,new动画点终对相view的距离 private TranslateAnimation createTranslateAnimation(Point oldOffset, Point newOffset) { TranslateAnimation translate = new TranslateAnimation( Animation.ABSOLUTE, oldOffset.x, Animation.ABSOLUTE, newOffset.x, Animation.ABSOLUTE, oldOffset.y, Animation.ABSOLUTE, newOffset.y); translate.setDuration(ANIMATION_DURATION); translate.setFillEnabled(true); translate.setFillAfter(true); translate.setInterpolator(new AccelerateDecelerateInterpolator()); return translate; } private void animateMoveToNewPosition(View targetView, Point oldOffset, Point newOffset) { AnimationSet set = new AnimationSet(true); Animation rotate = createFastRotateAnimation(); Animation translate = createTranslateAnimation(oldOffset, newOffset); set.addAnimation(rotate); set.addAnimation(translate); targetView.clearAnimation(); targetView.startAnimation(set); } private boolean aViewIsDragged() { return dragged != -1; } // 建创表现在最后的添加view private TextView createAddView() { if (add != null) { return add; } add = new TextView(getContext()); add.setBackgroundResource(R.drawable.preview_border); add.setGravity(Gravity.CENTER); add.setText("+"); if(mAddClickListener != null) { add.setOnClickListener(mAddClickListener); } return add; } }