这篇博客修改的是文件夹的缩略图,修改为九宫格。
原生的是一个圆形,而且最多只能显示四个app的缩略图,修改为国内常见的九宫格形式;
上代码
src/com/android/launcher3/folder/FolderIcon.java
可以看到这个FolderIcon是一个view,那么基本就可以确定这就是文件夹的缩略图了,但是找了一下没发现它有onDraw()方法,也没有onLayout()方法;
找了一会没有思路,这个时候我转变了思路,在folder包下面,发现src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java
这个类,有兴趣的同学可以看看,里面有三角函数,还有圆周率,因为原生的文件夹缩略图就是以圆形排列的,为了确定,修改这两个常量,就可以看出效果:
/* 20180702 modify begin */
// static final int MAX_NUM_ITEMS_IN_PREVIEW = 4;
static final int MAX_NUM_ITEMS_IN_PREVIEW = Integer.MAX_VALUE;
/* 20180702 modify end */
private static final int MIN_NUM_ITEMS_IN_PREVIEW = 2;
/* 20180702 modify begin */
private static final float MIN_SCALE = 0.22f;
/* 20180702 modify end */
到这里就可以确定文件夹缩略图的规则就是这个类做的了,那么我们就要修改一下这个规则:
@Override
public PreviewItemDrawingParams computePreviewItemDrawingParams(int index, int curNumItems,
PreviewItemDrawingParams params) {
......
transX = mTmpPoint[0];
transY = mTmpPoint[1];
/* 20180702 modify begin */
int padl = 15;
int padt = 15;
int tempIndex = index % 9;
transX = padl + mIconSize * MIN_SCALE * getCol(tempIndex) + getCol(tempIndex) * 5;
transY = padt + mIconSize * MIN_SCALE * (getRow(tempIndex) - 1) + (getRow(tempIndex) - 1) * 5;
/* 20180702 modify end */
if (params == null) {
params = new PreviewItemDrawingParams(transX, transY, totalScale, overlayAlpha);
} else {
params.update(transX, transY, totalScale);
params.overlayAlpha = overlayAlpha;
}
return params;
}
/* 20180702 modify begin */
private int getRow(int index) {
return index / 3 + 1;
}
private int getCol(int index) {
return (index) % 3;
}
/* 20180702 modify end */
文件夹的显示规则修改了,那么它的图形是怎么绘制出来的呢,偶然间让我发现了一个dispatchDraw()方法,再看dispatchDraw()里面,恍然大悟
src/com/android/launcher3/folder/FolderIcon.java -> dispatchDraw():
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (!mBackgroundIsVisible) return;
mPreviewItemManager.recomputePreviewDrawingParams();
if (!mBackground.drawingDelegated()) {
mBackground.drawBackground(canvas);
}
if (mFolder == null) return;
if (mFolder.getItemCount() == 0 && !mAnimating) return;
final int saveCount;
if (canvas.isHardwareAccelerated()) {
saveCount = canvas.saveLayer(0, 0, getWidth(), getHeight(), null,
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
} else {
saveCount = canvas.save(Canvas.CLIP_SAVE_FLAG);
/* 20180702 modify begin */
// if (mPreviewLayoutRule.clipToBackground()) {
// canvas.clipPath(mBackground.getClipPath(), Region.Op.INTERSECT);
// }
/* 20180702 modify end */
}
mPreviewItemManager.draw(canvas);
/* 20180702 modify begin */
// if (mPreviewLayoutRule.clipToBackground() && canvas.isHardwareAccelerated()) {
// mBackground.clipCanvasHardware(canvas);
// }
/* 20180702 modify end */
canvas.restoreToCount(saveCount);
/* 20180702 modify begin */
// if (mPreviewLayoutRule.clipToBackground() && !mBackground.drawingDelegated()) {
// mBackground.drawBackgroundStroke(canvas);
// }
//
/* 20180702 modify end */
drawBadge(canvas);
}
最后在修改一个缩略图背景,
src/com/android/launcher3/folder/PreviewBackground.java :
public void drawBackground(Canvas canvas) {
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(getBgColor());
drawCircle(canvas, 0 /* deltaRadius */);
/* 20180702 modify begin */
// drawShadow(canvas);
/* 20180702 modify end */
}
private void drawCircle(Canvas canvas,float deltaRadius) {
float radius = getScaledRadius();
/* 20180702 modify begin */
// canvas.drawCircle(radius + getOffsetX(), radius + getOffsetY(),
// radius - deltaRadius, mPaint);
canvas.drawRoundRect(0 + getOffsetX(), 0 + getOffsetY(), radius * 2 + getOffsetX(),
radius * 2 + getOffsetY(), 30, 30, mPaint);
/* 20180702 modify end */
}
到这里,我们的文件夹缩略提就以九宫格展示了;
但是仍然遗留了问题,就是当我们的文件夹第一页满了的情况下,在文件夹外长按一个APP,文件夹的缩略图应该滑动到文件夹的当前页;
这个看了一会,找到了文件夹动画(打开文件夹,滑动到第二页,关闭文件夹后,缩略图的动画)的地方,但是没修改成功,现在附上代码,如果有同学弄好了,还请指教
src/com/android/launcher3/folder/PreviewItemManager.java:
void onFolderClose(int currentPage) {
// If we are not closing on the first page, we animate the current page preview items
// out, and animate the first page preview items in.
mShouldSlideInFirstPage = currentPage != 0;
if (mShouldSlideInFirstPage) {
mCurrentPageItemsTransX = 0;
buildParamsForPage(currentPage, mCurrentPageParams, false);
onParamsChanged();
ValueAnimator slideAnimator = ValueAnimator.ofFloat(0, ITEM_SLIDE_IN_OUT_DISTANCE_PX);
slideAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mCurrentPageItemsTransX = (float) valueAnimator.getAnimatedValue();
onParamsChanged();
}
});
slideAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mCurrentPageParams.clear();
}
});
slideAnimator.setStartDelay(SLIDE_IN_FIRST_PAGE_ANIMATION_DURATION_DELAY);
slideAnimator.setDuration(SLIDE_IN_FIRST_PAGE_ANIMATION_DURATION);
slideAnimator.start();
}
}