最近研究页面删除,稍微总结一下,以后继续补充:

本文主要讲android4.0 Launcher添加页面辑编功能,式样同三星的平板。

一、已实现功能:

1、页面增减(最多8个页面、动拖删除、最后一个添加页面、有内容的页面弗成删除)

2、由自动拖换交置位

3、页面置位布局(完整仿三星置位布局)、前目是定固巨细的。。。为什么要仿它,纠结

布局图:

二、开始思绪

1、自定义一个view,实现添加、由自动拖、删除等功能

2、开始页面辑编时,将已有的页面成生缩略图传入到自定义的view中表现

3、辑编完成后,将新的页面次序传出来,对Workspace的CellLayout停止重新排序(调整次序,成生新加的页面,删除删除了的页面)

4、新更据数库中CellLayout面上item的screen属性

5、将现有的页面数量定入到件文中或者据数库

6、动启launcher时,workspace中CellLayout的数量初始化通过读取已存保的页面据数

三、关相代码

1、自定义的页面辑编View-------HomeEditView.java

package com.launcher.edit;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;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.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.TextView;import com.android.launcher.R;/*** 页面辑编* 前当页面是不是可删除用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 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 = 250;private static final int BIG_HEIGHT = 250;// 水平两页面之间的间隙private static final int PAGE_GAP_WIDTH = 5;// 竖直两页面之间的间隙private static final int PAGE_GAP_HEIGHT = 5;// 删除区域的高度private static final int DELETE_ZONE_HEIGHT = 40;int dragged = -1;// 前当是不是在挪动viewprivate boolean movingView = false;private int dragLeft;private int dragTop;private TextView add;public interface OnClickPageListener {public void onClickPage(int index, List<PageInfo> pages);}private OnClickPageListener clickPage;public void setOnClickPageListener(OnClickPageListener listener) {this.clickPage = listener;}private OnClickListener onClickListener = new OnClickListener() {@Overridepublic void onClick(View v) {Log.d(TAG, "onClick");if (v == add) {View view = createView(getChildCount() - 2);addView(view, getChildCount() - 2);// view.setOnClickListener(this);if (getChildCount() == 10) {Log.d(TAG, "已到达最大页面数, 删除添加按钮");removeView(add);}requestLayout();} else {if (clickPage != null) {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.d(TAG, "tag : " + info.originPage);info.currentPage = i;pages.add(info);}clickPage.onClickPage(0, 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;private DeleteDropZoneView deleteZone;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 addViews(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);}if (views.size() < 8) {addView(createAddView());}// 将删除区域放到最面后createDeleteZone();}private void printTag() {for (int i = 0; i < getChildCount(); i++) {View child = getChildAt(i);// Log.d(TAG, "Tag : " + child.getTag());}// Log.d(TAG, "-----------------------------");}@Overridepublic 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();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.d(TAG, "clickedView : " + clickedView);if(clickedView != null)onClickListener.onClick(clickedView);}} else {hideDeleteView();manageChildrenReordering();movingView = false;dragged = -1;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);if (draggedDeleted) {View view = getChildAt(dragged);int id = view.getId();Log.d(TAG, "id : " + id);if (id > 0) {draggedDeleted = false;}}if (draggedDeleted) {animateDeleteDragged();reorderChildrenWhenDraggedIsDeleted();} else {reorderChildren();}}// 当有页面被删除时,重新排列viewprivate 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() {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);}}// 重新排列viewprivate List<View> reeorderView(List<View> children) {View[] views = new View[children.size()];for (int i = 0; i < children.size(); i++) {int position = newPositions.get(i, -1);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.d(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) {int viewAtPosition = currentViewAtPosition(target);if (getChildAt(viewAtPosition) == add) {return;}// 源始置位View origin = getChildAt(viewAtPosition);int originLeft = origin.getLeft();int originTop = origin.getTop();if (viewAtPosition == dragged) {originLeft = dragLeft;originTop = dragTop;}// 前当置位View curr = getChildAt(target);int currLeft = curr.getLeft();int currTop = curr.getTop();if (target == dragged) {currLeft = dragLeft;currTop = dragTop;}// 将要到达置位View tar = getChildAt(newPositions.get(dragged, dragged));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明说:最后的deleteZonefor (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;}// 挪动被拖曳的viewprivate 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);}}}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {int count = getChildCount() - 1;// updateSize();Log.d(TAG, "count == " + count);if (count < 3) {int left = getWidth() / 2 - (SMALL_WIDTH * 2 + PAGE_GAP_WIDTH) / 2;for (int i = 0; i < count; i++) {View child = getChildAt(i);if (child.getVisibility() == View.GONE) {continue;}child.layout(left, DELETE_ZONE_HEIGHT, left + SMALL_WIDTH,SMALL_HEIGHT + DELETE_ZONE_HEIGHT);left += SMALL_WIDTH + PAGE_GAP_WIDTH;}} else if (count == 3) {int left = getWidth() / 2 - (SMALL_WIDTH * 2 + PAGE_GAP_WIDTH) / 2;for (int i = 0; i < count; i++) {View child = getChildAt(i);if (child.getVisibility() == View.GONE) {continue;}if (i == 2) {child.layout(getWidth() / 2 - SMALL_WIDTH / 2, SMALL_HEIGHT+ PAGE_GAP_HEIGHT + DELETE_ZONE_HEIGHT, getWidth()/ 2 - SMALL_WIDTH / 2 + SMALL_WIDTH, SMALL_HEIGHT* 2 + PAGE_GAP_HEIGHT + DELETE_ZONE_HEIGHT);} else {child.layout(left, DELETE_ZONE_HEIGHT, left + SMALL_WIDTH,SMALL_HEIGHT + DELETE_ZONE_HEIGHT);left += SMALL_WIDTH + PAGE_GAP_WIDTH;}}} else if (count == 4) {int left = getWidth() / 2 - (SMALL_WIDTH * 2 + PAGE_GAP_WIDTH) / 2;int left2 = getWidth() / 2 - (SMALL_WIDTH * 2 + PAGE_GAP_WIDTH) / 2;for (int i = 0; i < count; i++) {View child = getChildAt(i);if (child.getVisibility() == View.GONE) {continue;}if (i >= 2) {child.layout(left2, SMALL_HEIGHT + PAGE_GAP_HEIGHT+ DELETE_ZONE_HEIGHT, left2 + SMALL_WIDTH,SMALL_HEIGHT * 2 + PAGE_GAP_HEIGHT+ DELETE_ZONE_HEIGHT);left2 += SMALL_WIDTH + PAGE_GAP_WIDTH;} else {child.layout(left, DELETE_ZONE_HEIGHT, left + SMALL_WIDTH,SMALL_HEIGHT + DELETE_ZONE_HEIGHT);left += SMALL_WIDTH + PAGE_GAP_WIDTH;}}} else if (count == 5) {int left1 = getWidth() / 2 - (BIG_WIDTH * 2 + PAGE_GAP_WIDTH) / 2;int left2 = getWidth() / 2 - (BIG_WIDTH / 2);int left3 = getWidth() / 2 - (BIG_WIDTH * 2 + PAGE_GAP_WIDTH) / 2;for (int i = 0; i < count; i++) {View child = getChildAt(i);if (child.getVisibility() == View.GONE) {continue;}if (i < 2) {child.layout(left1, DELETE_ZONE_HEIGHT, left1 + BIG_WIDTH,BIG_HEIGHT + DELETE_ZONE_HEIGHT);left1 += BIG_WIDTH + PAGE_GAP_WIDTH;} else if (i == 2) {child.layout(left2, BIG_HEIGHT + PAGE_GAP_HEIGHT+ DELETE_ZONE_HEIGHT, left2 + BIG_WIDTH, BIG_HEIGHT* 2 + PAGE_GAP_HEIGHT + DELETE_ZONE_HEIGHT);} 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;}}} else if (count == 6) {int left1 = getWidth() / 2 - (BIG_WIDTH * 2 + PAGE_GAP_WIDTH) / 2;int left2 = left1;int left3 = getWidth() / 2 - (BIG_WIDTH * 2 + PAGE_GAP_WIDTH) / 2;for (int i = 0; i < count; i++) {View child = getChildAt(i);if (child.getVisibility() == View.GONE) {continue;}if (i < 2) {child.layout(left1, DELETE_ZONE_HEIGHT, left1 + BIG_WIDTH,BIG_HEIGHT + DELETE_ZONE_HEIGHT);left1 += BIG_WIDTH + PAGE_GAP_WIDTH;} else if (i >= 2 && i < 4) {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;}}} else if (count == 7) {int left1 = getWidth() / 2 - (BIG_WIDTH * 2 + PAGE_GAP_WIDTH) / 2;int left2 = getWidth() / 2 - (BIG_WIDTH * 3 + 2 * PAGE_GAP_WIDTH)/ 2;int left3 = getWidth() / 2 - (BIG_WIDTH * 2 + PAGE_GAP_WIDTH) / 2;for (int i = 0; i < count; i++) {View child = getChildAt(i);if (child.getVisibility() == View.GONE) {continue;}if (i < 2) {child.layout(left1, DELETE_ZONE_HEIGHT, left1 + BIG_WIDTH,BIG_HEIGHT + DELETE_ZONE_HEIGHT);left1 += BIG_WIDTH + PAGE_GAP_WIDTH;} else if (i >= 2 && 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;}}} else if (count == 8) {int left1 = getWidth() / 2 - (BIG_WIDTH * 3 + 2 * PAGE_GAP_WIDTH)/ 2;int left2 = getWidth() / 2 - (BIG_WIDTH * 2 + PAGE_GAP_WIDTH) / 2;int left3 = left1;for (int i = 0; i < count; i++) {View child = getChildAt(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;}}}}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {Log.d(TAG, "onMeasure");super.onMeasure(widthMeasureSpec, heightMeasureSpec);int count = getChildCount();//     updateSize();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));}}measureChild(deleteZone, MeasureSpec.makeMeasureSpec(getWidth(),MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(DELETE_ZONE_HEIGHT, MeasureSpec.EXACTLY));}private float getPixelFromDip(int size) {Resources r = getResources();float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size,r.getDisplayMetrics());return px;}@Overridepublic boolean onLongClick(View v) {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;}// 点击添加时、建创一个新viewprivate View createView(int count) {TextView tv = new TextView(mContext);tv.setWidth(50);tv.setHeight(50);tv.setBackgroundColor(Color.CYAN);tv.setTag(-1);tv.setId(0);tv.setText("" + count);return tv;}// 表现删除区域private void popDeleteView() {deleteZone.setVisibility(View.VISIBLE);deleteZone.layout(0, 0, deleteZone.getMeasuredWidth(),deleteZone.getMeasuredHeight());}private void createDeleteZone() {deleteZone = new DeleteDropZoneView(getContext());addView(deleteZone);deleteZone.setVisibility(View.GONE);}// 建创表现在最后的添加viewprivate TextView createAddView() {if (add != null) {return add;}add = new TextView(getContext());add.setBackgroundColor(Color.CYAN);add.setGravity(Gravity.CENTER);add.setText("+");return add;}private void hideDeleteView() {deleteZone.setVisibility(View.GONE);}// 动拖放开时,判断是不是在删除区域中private boolean touchUpInDeleteZoneDrop(int x, int y) {Rect zone = new Rect();deleteZone.getHitRect(zone);if (zone.intersect(x, y, x + 1, y + 1)) {deleteZone.smother();return true;}return false;}// 挪动到删除区域时,高亮表现private void manageDeleteZoneHover(int x, int y) {Rect zone = new Rect();deleteZone.getHitRect(zone);if (zone.intersect(x, y, x + 1, y + 1)) {deleteZone.highlight();} else {deleteZone.smother();}}
}class DeleteDropZoneView extends View {private Paint textPaintStraight;private Paint textPaintRed;private Paint bitmapPaint;private Paint bitmapPaintRed;private boolean straight = true;private Bitmap trash;private Rect bounds;public DeleteDropZoneView(Context context) {super(context);bounds = new Rect();textPaintStraight = createTextPaint();textPaintStraight.setColor(Color.WHITE);textPaintRed = createTextPaint();textPaintRed.setColor(Color.RED);bitmapPaint = createBaseBitmapPaint();bitmapPaintRed = createBaseBitmapPaint();ColorFilter filter = new LightingColorFilter(Color.RED, 1);bitmapPaintRed.setColorFilter(filter);setBackgroundColor(Color.BLACK);getBackground().setAlpha(200);}private Paint createTextPaint() {Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);textPaint.setStyle(Style.FILL);textPaint.setTextAlign(Paint.Align.CENTER);textPaint.setTypeface(Typeface.DEFAULT_BOLD);return textPaint;}private Paint createBaseBitmapPaint() {Paint bitmapPaint = new Paint();bitmapPaint.setAntiAlias(true);bitmapPaint.setFilterBitmap(true);bitmapPaint.setDither(true);return bitmapPaint;}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);int measuredHeight = getMeasuredHeight();int measuredWidth = getMeasuredWidth();String removeString = "Remove";// getResources().getString(R.string.removeItem);initTrashIcon();textPaintStraight.getTextBounds(removeString, 0, 6, bounds);int proportion = 3 * measuredHeight / 4;if (straight) {textPaintStraight.setTextSize(proportion);canvas.drawText(removeString,(measuredWidth / 2) + (trash.getWidth() / 2) + 5,measuredHeight - ((measuredHeight - bounds.height()) / 2),textPaintStraight);canvas.drawBitmap(trash, (measuredWidth / 2) - (bounds.width() / 2)- (trash.getWidth() / 2) - 10, 0, bitmapPaint);} else {textPaintRed.setTextSize(proportion);canvas.drawText(removeString,(measuredWidth / 2) + (trash.getWidth() / 2) + 5,measuredHeight - ((measuredHeight - bounds.height()) / 2),textPaintRed);canvas.drawBitmap(trash, (measuredWidth / 2) - (bounds.width() / 2)- (trash.getWidth() / 2) - 10, 0, bitmapPaintRed);}}private void initTrashIcon() {if (trash == null) {trash = getImage(R.drawable.content_discard, getMeasuredHeight(),getMeasuredHeight());}}public void highlight() {straight = false;invalidate();}public void smother() {straight = true;invalidate();}private Bitmap getImage(int id, int width, int height) {Bitmap bmp = BitmapFactory.decodeResource(getResources(), id);Bitmap img = Bitmap.createScaledBitmap(bmp, width, height, true);bmp.recycle();invalidate();return img;}}
每日一道理
漫漫人生路,谁都难免会遭遇各种失意或厄运。在凄风苦雨 惨雾愁云的考验面前,一个强者,是不会向命运低头的。风再冷,不会永远不息;雾再浓,不会经久不散。风息雾散,仍是阳光灿烂。

2、launcher.xml中添加自定义的view,注意要Gone

<com.launcher.edit.HomeEditViewandroid:id="@+id/gridview"android:visibility="gone"android:layout_width="fill_parent"android:layout_height="fill_parent" />

3、在Launcher.java中添加开始辑编方法(触发条件自已加吧), mDragGrid我定义成了成员字段

private void startEdit() {Log.d(TAG, "*******onLongClick AllAppsButton**********");mDragGrid = (HomeEditView) findViewById(R.id.gridview);mDragGrid.setOnClickPageListener(listener);List<View> views = new ArrayList<View>();for (int i = 0; i < mWorkspace.getChildCount(); i++) {// 将前当已有的页面成生缩略图,放到HomeEditView中停止表现CellLayout view = (CellLayout) mWorkspace.getChildAt(i);ImageView image = new ImageView(this);Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);//绘制  final Canvas c = new Canvas(bitmap);  //设置比例  view.dispatchDraw(c);   image.setImageBitmap(bitmap);  image.setBackgroundColor(Color.GRAY);// 通过id判断是不是可以删除if (((ViewGroup) view.getChildAt(0)).getChildCount() != 0) {image.setId(1);} else {image.setId(0);}views.add(image);}mDragGrid.addViews(views);mDragGrid.setBackgroundColor(Color.RED);mDragGrid.setVisibility(View.VISIBLE);mWorkspace.setVisibility(View.INVISIBLE); mHotseat.setVisibility(View.GONE);mSearchDropTargetBar.setVisibility(View.GONE);mDockDivider.setVisibility(View.GONE);}private OnClickPageListener listener = new OnClickPageListener() {@Overridepublic void onClickPage(int index, List<PageInfo> pages) {Log.d(TAG, "onClickPage");mWorkspace.setVisibility(View.VISIBLE); mHotseat.setVisibility(View.VISIBLE);mSearchDropTargetBar.setVisibility(View.VISIBLE);mDockDivider.setVisibility(View.VISIBLE);mDragGrid.setVisibility(View.GONE);mWorkspace.reorderChildren(pages);}};

4、Workspace.java中重新排列CellLayout代码

// 页面辑编完成后,重新排列CellLayoutpublic void reorderChildren(List<PageInfo> pages) {List<View> views = removeOldViews();View[] newViews = new View[pages.size()];for (int i = 0; i < newViews.length; i++) {PageInfo info = pages.get(i);if (info.originPage != -1) {newViews[i] = views.get(info.originPage);// 新更此页面上的item的screen信息CellLayout cell = (CellLayout) newViews[i];CellLayoutChildren chi = (CellLayoutChildren) cell.getChildAt(0);for (int j = 0; j < chi.getChildCount(); j++) {ItemInfo in = (ItemInfo) chi.getChildAt(j).getTag();// 设定新的screenin.screen = i;LauncherModel.updateItemInDatabase(getContext(), in);}} else {newViews[i] = new CellLayout(mLauncher);}}for (int i = 0; i < newViews.length; i++) {addView(newViews[i]);}requestLayout();}private List<View> removeOldViews() {List<View> list = new ArrayList<View>();for (int i = 0; i < getChildCount(); i++) {View view = getChildAt(i);list.add(view);}for (View view : list) {removeView(view);}return list;}

5、Workspace.java中初始化CellLayout代码, 此方法最好在构造方法中调initWorkspace()方法的前一行调用(没搞明白,一开始就调用的话会出问题)

private void initCells(Context context) {SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());int count = sp.getInt("screen_count", 5);for (int i = 0; i < count; i++) {CellLayout cl = new CellLayout(context);this.addView(cl);}}

6、CellLayout.java的单个参数的构造方法要改

public CellLayout(Context context) {super(context);// A ViewGroup usually does not draw, but CellLayout needs to draw a// rectangle to show// the user where a dragged item will land when dropped.setWillNotDraw(false);mOriginalCellWidth = mCellWidth = getResources().getDimensionPixelSize(R.dimen.workspace_cell_width);mOriginalCellHeight = mCellHeight = getResources().getDimensionPixelSize(R.dimen.workspace_cell_height);mWidthGap = mOriginalWidthGap = getResources().getDimensionPixelSize(R.dimen.workspace_width_gap);mHeightGap = mOriginalHeightGap = getResources().getDimensionPixelSize(R.dimen.workspace_height_gap);mMaxGap = getResources().getDimensionPixelSize(R.dimen.workspace_max_gap);setPadding(getResources().getDimensionPixelSize(R.dimen.workspace_left_padding),getResources().getDimensionPixelSize(R.dimen.workspace_top_padding),getResources().getDimensionPixelSize(R.dimen.workspace_right_padding),getResources().getDimensionPixelSize(R.dimen.workspace_bottom_padding));mCountX = LauncherModel.getCellCountX();mCountY = LauncherModel.getCellCountY();mOccupied = new boolean[mCountX][mCountY];setAlwaysDrawnWithCacheEnabled(false);final Resources res = getResources();mNormalBackground = res.getDrawable(R.drawable.homescreen_blue_normal_holo);mActiveGlowBackground = res.getDrawable(R.drawable.homescreen_blue_strong_holo);mOverScrollLeft = res.getDrawable(R.drawable.overscroll_glow_left);mOverScrollRight = res.getDrawable(R.drawable.overscroll_glow_right);mForegroundPadding = res.getDimensionPixelSize(R.dimen.workspace_overscroll_drawable_padding);mNormalBackground.setFilterBitmap(true);mActiveGlowBackground.setFilterBitmap(true);// Initialize the data structures used for the drag visualization.mCrosshairsDrawable = res.getDrawable(R.drawable.gardening_crosshairs);mEaseOutInterpolator = new DecelerateInterpolator(2.5f); // Quint ease// out// Set up the animation for fading the crosshairs in and outint animDuration = res.getInteger(R.integer.config_crosshairsFadeInTime);mCrosshairsAnimator = new InterruptibleInOutAnimator(animDuration,0.0f, 1.0f);mCrosshairsAnimator.getAnimator().addUpdateListener(new AnimatorUpdateListener() {public void onAnimationUpdate(ValueAnimator animation) {mCrosshairsVisibility = ((Float) animation.getAnimatedValue()).floatValue();invalidate();}});mCrosshairsAnimator.getAnimator().setInterpolator(mEaseOutInterpolator);mDragCell[0] = mDragCell[1] = -1;for (int i = 0; i < mDragOutlines.length; i++) {mDragOutlines[i] = new Point(-1, -1);}// When dragging things around the home screens, we show a green outline// of// where the item will land. The outlines gradually fade out, leaving a// trail// behind the drag path.// Set up all the animations that are used to implement this fading.final int duration = res.getInteger(R.integer.config_dragOutlineFadeTime);final float fromAlphaValue = 0;final float toAlphaValue = (float) res.getInteger(R.integer.config_dragOutlineMaxAlpha);Arrays.fill(mDragOutlineAlphas, fromAlphaValue);for (int i = 0; i < mDragOutlineAnims.length; i++) {final InterruptibleInOutAnimator anim = new InterruptibleInOutAnimator(duration, fromAlphaValue, toAlphaValue);anim.getAnimator().setInterpolator(mEaseOutInterpolator);final int thisIndex = i;anim.getAnimator().addUpdateListener(new AnimatorUpdateListener() {public void onAnimationUpdate(ValueAnimator animation) {final Bitmap outline = (Bitmap) anim.getTag();// If an animation is started and then stopped very quickly,// we can still// get spurious updates we've cleared the tag. Guard against// this.if (outline == null) {if (false) {Object val = animation.getAnimatedValue();Log.d(TAG, "anim " + thisIndex + " update: " + val+ ", isStopped " + anim.isStopped());}// Try to prevent it from continuing to runanimation.cancel();} else {mDragOutlineAlphas[thisIndex] = (Float) animation.getAnimatedValue();final int left = mDragOutlines[thisIndex].x;final int top = mDragOutlines[thisIndex].y;CellLayout.this.invalidate(left, top,left + outline.getWidth(),top + outline.getHeight());}}});// The animation holds a reference to the drag outline bitmap as// long is it's// running. This way the bitmap can be GCed when the animations are// complete.anim.getAnimator().addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {if ((Float) ((ValueAnimator) animation).getAnimatedValue() == 0f) {anim.setTag(null);}}});mDragOutlineAnims[i] = anim;}mBackgroundRect = new Rect();mForegroundRect = new Rect();mChildren = new CellLayoutChildren(context);mChildren.setCellDimensions(mCellWidth, mCellHeight, mWidthGap,mHeightGap);addView(mChildren);setBackgroundColor(Color.BLUE);}

7、PageInfo.java

public class PageInfo implements Comparable<PageInfo> {// 未辑编前是哪个页面public int originPage = -1;// 辑编完成后是哪个页面public int currentPage = -1;@Overridepublic int compareTo(PageInfo another) {return currentPage - another.currentPage;}
}

最后来一张手机测的效果图

还有好多地方没有完善:1、设置主页       2、定固巨细(可以改成定固dip)、因为布局不平均自适应可能不行  等等。。。

文章结束给大家分享下程序员的一些笑话语录: 一程序员告老还乡,想安度晚年,于是决定在书法上有所造诣。省略数字……,准备好文房4宝,挥起毛笔在白纸上郑重的写下:Hello World

转载于:https://www.cnblogs.com/xinyuyuanm/archive/2013/04/23/3037389.html

页面删除android4.0 Launcher仿三星平板workspace页面编辑(即页面增减)相关推荐

  1. android锁屏快捷键设置,Android4.0+锁屏程序开发——设置锁屏页面篇

    [如何开发一个锁屏应用] 想要开发一个锁屏应用,似乎很难,其实并没有想象中那么难. 从本质上来说,锁屏界面也只是一个Activity而已,只是这个界面比较特殊,在我们点亮屏幕的时候,这个界面就会出现. ...

  2. Android4.0 Launcher 源码分析系列(二)

    上一节我们研究了Launcher的整体结构,这一节我们看看整个Laucher的入口点,同时Laucher在加载了它的布局文件Laucher.xml时都干了些什么. 我们在源代码中可以找到Launche ...

  3. PDF页面删除怎么操作

    当我们有时候在编辑PDF文件时,要知道如何操作能处理好编辑的需求,这样我们才能完成更多相应的学习和工作.最近有小伙伴咨询遇到了个PDF文件中的页面内容重复的问题,对于这种不再需要某些页面内容时,则需要 ...

  4. android隐藏底部栏,Android4.0平板开发之隐藏底部任务栏的方法

    本文实例讲述了Android4.0平板开发之隐藏底部任务栏的方法.分享给大家供大家参考,具体如下: getWindow().getDecorView().setSystemUiVisibility(V ...

  5. android 4.0.3固件,昂达平板即将发Android4.0.3优化固件

    泡泡网平板电脑频道2月16日 全线升级Android 4.0.首发Android 4.0.3,如此频繁的不断升级,让昂达A10平板在消费者心中攒足了人气,加上强劲的性能与丰富的功能,昂达依旧是国内平板 ...

  6. Android4.0平板通过OTG线连接Acr122U读取智慧校园卡

    Android4.0平板通过OTG线连接Acr122U读取智慧校园卡,使用读卡器官方提供的SDK,发送APDU的FF CA 00 00 00指令读取卡号UID,具体代码稍后上传.

  7. android4.0浏览器在eclipse中编译的步骤

    工程源码: 注意: 如果下载已经修过的源码,只要进行3.4.8步骤就应该可以了. eclipse版本:adt-bundle-windows (Android Developer Tools Build ...

  8. Android4.0 SDK新功能详解

    Android 4.0 平台 API等级:14 Android 4.0 是一次重要的平台发布版,为用户和应用程序开发者增加了大量的新特性.在下面我们将讨论的所有新特性和API中,因为它将 Androi ...

  9. Android4.0新特性 中文翻译

    转自http://www.eoeandroid.com/thread-103300-1-1.html android4.0 SDK发布有一段时间了,在eoe上找到了翻译过的新特性说明,特转载 Andr ...

  10. Android4.0新的SDK新特性 (转)

    Android 4.0 是一次重要的平台发布版,为用户和应用程序开发者增加了大量的新特性.在下面我们将讨论的所有新特性和API中,因为它将 Android 3.x 版本中广泛使用的API和全息图像主题 ...

最新文章

  1. C指针9:指针数组(即数组中的每个元素都是指针)
  2. tensorflow 使用CPU而不使用GPU的问题解决
  3. 1055. 集体照 (25)
  4. 计算机二级操作范文,计算机二级考试(范文).doc
  5. 不具有继承关系的Delegate如何进行类型转换?
  6. Java并发编程之并发容器ConcurrentHashMap(JDK1.7)解析
  7. SQL取分组中前、后几条数据
  8. ICSharpCode.SharpZipLib 压缩、解压文件 附源码
  9. 百度最全的LINUX和Redhat学习教程下载帖大全
  10. Ubuntu用ssh连接虚拟机
  11. YII composer全局安装
  12. WINDOWS XP 桌面主题的安装制作
  13. 用 Mathematica 破解密码
  14. android中小数怎么定义,android 如何保留数据两位小数
  15. Vue设计模式,发布订阅,响应式原理(简略版)
  16. 数据库 - 数据库角色
  17. 穿越鸿蒙电视剧,2020“必追”的5部穿越剧,每一部都有高颜值,剧荒的别错过!...
  18. laravel jwt attempt 总是返回false
  19. ARM neon详解
  20. Redis详解(3)数据持久化机制

热门文章

  1. SQL server 2005 数据库只能用计算机名连接不能用IP地址
  2. 33. 把数组排成最小的数(C++版本)
  3. 查找算法之三 插值查找(C++版本)
  4. opendir是安全重入函数吗_redis实现分布式锁,与jdk可重入锁ReentrantLock的原理对比剖析...
  5. 五万字整理Mybatis 入门只需要一篇文章
  6. MapReduce job任务源码提交流程
  7. redis的发布和订阅
  8. python中pip有啥用_python的pip有什么用
  9. 前端怎么通过后台来判断已读状态_微前端自检清单
  10. gnuradio上怎么使用python文件_使用Python下载文件的简单示例