1.直接上代码
java
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
public class ViewUtils {
private static final String TAG = "ViewUtils";
private static boolean isScrollInteraction;//是否从桌面左滑
public static Launcher.LauncherOverlay addNegativeScreen(Launcher launcher, ViewGroup parent) {
LogUtils.init(launcher);
View nsv = LayoutInflater.from(launcher).inflate(R.layout.negative_screen, null);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
nsv.setLayoutParams(lp);
parent.addView(nsv, 0); // 插入到首位(布局最左边)
int width = Resources.getSystem().getDisplayMetrics().widthPixels;
nsv.setTranslationX(-width);//位移到左边屏幕外
return new Launcher.LauncherOverlay() {
@Override
public void onScrollInteractionBegin() {
isScrollInteraction = launcher.getWorkspace().getCurrentPage() == 0;//是否为第一页开始
Log.i(TAG, "onScrollInteractionBegin");
}
@Override
public void onScrollInteractionEnd() {
isScrollInteraction = false;
Log.i(TAG, "onScrollInteractionEnd");
}
@Override
public void onScrollChange(float progress, boolean rtl) {
float disW = progress * width;//x轴滑动距离
Log.i(TAG, "onScrollChange-progress=" + progress + ",rtl=" + rtl + ",width=" + width + ",disW=" + disW);
}
@Override
public void setOverlayCallbacks(Launcher.LauncherOverlayCallbacks callbacks) {
Log.i(TAG, "setOverlayCallbacks");
}
};
}
private static float mDx, mDy, disX, disY;//按下坐标值及距离
private static final float MIN_DIS_X = 4;//最小滑动距离
private static final float MIN_DIS_Y = 4;//最小滑动距离
private static int consumedType = 0;//消费事件类型(0-默认滑动,1-左右滑动,2-上下滑动,3-其他滑动)
static boolean isFling = false;//是否快速滑动
private static boolean mNsvVisible = false;//负一屏是否可见
/**
* 触摸事件处理
*
* @param launcher
* @param viewGroup
* @param ev
* @return
*/
public static boolean setDispatchTouchEvent(Launcher launcher, ViewGroup viewGroup, MotionEvent ev) {
View nsv = viewGroup.getChildAt(0);
View rightView = viewGroup.getChildAt(1);
int width = viewGroup.getWidth();
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
isScrollInteraction = false;
isFling = false;
consumedType = 0;
mDx = ev.getX();
mDy = ev.getY();
disX = 0;
disY = 0;
Log.i(TAG, "setDispatchTouchEvent-down-width=" + width + ",mDx=" + mDx + ",mDy=" + mDy);
break;
case MotionEvent.ACTION_MOVE:
float mx = ev.getX();
float my = ev.getY();
disX = mx - mDx;//x轴滑动距离
disY = my - mDy;//y轴滑动距离
if (Math.abs(disX) > Math.abs(disY) && consumedType == 0 && Math.abs(disX) > MIN_DIS_X) {//是否为-左右滑动
if (isScrollInteraction || mNsvVisible ) {//从桌面左滑判断 或 已显示负一屏判断
consumedType = 1;
}
} else if (Math.abs(disY) > Math.abs(disX) && consumedType == 0 && Math.abs(disY) > MIN_DIS_Y) {//是否为-上下滑动
consumedType = 2;
}
Log.i(TAG, "setDispatchTouchEvent-move-width=" + width + ",mx=" + mx + ",disX=" + disX + ",disY=" + disY +
",consumedType=" + consumedType + ",isScrollInteraction=" + isScrollInteraction + ",mNsvVisible=" + mNsvVisible);
float nsTx = nsv.getTranslationX() + disX;
float rvTx = rightView.getTranslationX() + disX;
if (consumedType == 1) {
if (disX > 0) {//往右滑
//你的逻辑...
nsv.setTranslationX(Math.min(nsTx, 0));
rightView.setTranslationX(Math.min(rvTx, width));
//negativeScreen.setTranslationX(nsTx);
//rightView.setTranslationX(rvTx);
float alpha = rightView.getTranslationX() / width;
nsv.setAlpha(alpha);
rightView.setAlpha(1 - nsv.getAlpha());
Log.i(TAG, "move=往右滑=mDx=" + mDx + ",mx=" + mx + ",disX=" + disX + ",alpha=" + alpha);
} else {//往左滑
//你的逻辑...
nsv.setTranslationX(Math.max(nsTx, -width));
rightView.setTranslationX(Math.max(rvTx, 0));
//negativeScreen.setTranslationX(nsTx);
//rightView.setTranslationX(rvTx);
float alpha = rightView.getTranslationX() / width;
rightView.setAlpha(1 - alpha);
nsv.setAlpha(1 - rightView.getAlpha());
Log.i(TAG, "move=往左滑=mDx=" + mDx + ",mx=" + mx + ",disX=" + disX + ",alpha=" + alpha);
}
if (Math.abs(disX) > 100) {//判断快速滑动值
isFling = true;
}
}
mDx = mx;//替换x轴坐标值
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (mNsvVisible) {//负一屏可见时
if (isFling && disX < 0) {//快速右滑
playAnim(nsv, rightView, 80, width, false);//执行动画,不显示负一屏
} else {
playAnim(nsv, rightView, isFling ? 80 : 200, width, width - rightView.getTranslationX() <= width / 4);//执行动画,负一屏是否可见
}
} else {
playAnim(nsv, rightView, isFling ? 80 : 200, width, (isFling && disX > 0) || rightView.getTranslationX() >= width / 4);//执行动画,负一屏是否可见
}
Log.i(TAG, "setDispatchTouchEvent-up-cancel-x=" + ev.getX() + ",mNsvVisible=" + mNsvVisible + ",Fling-disX=" + disX + ",isFling=" + isFling);
break;
}
return consumedType == 1;
}
/**
* 执行动画
*
* @param nsv
* @param rightView
* @param duration
* @param width
* @param isShowNsv 是否显示负一屏
*/
private static void playAnim(View nsv, View rightView, long duration, int width, boolean isShowNsv) {
// nsv 两个独立动画
ObjectAnimator alpha1 = ObjectAnimator.ofFloat(nsv, "alpha", nsv.getAlpha(), isShowNsv ? 1f : 0);
ObjectAnimator translationX1 = ObjectAnimator.ofFloat(nsv, "translationX", nsv.getTranslationX(), isShowNsv ? 0 : -width);
AnimatorSet set1 = new AnimatorSet();
set1.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation, boolean isReverse) {
mNsvVisible = isShowNsv;//修改负一屏状态为可见
Log.i(TAG, "playAnim-set1-onAnimationEnd-mNsvVisible=" + mNsvVisible + ",isShowNsv=" + isShowNsv);
}
});
set1.playTogether(alpha1, translationX1); // 同步执行
set1.setDuration(duration);
set1.start();
// rightView 两个独立动画
ObjectAnimator alpha2 = ObjectAnimator.ofFloat(rightView, "alpha", rightView.getAlpha(), isShowNsv ? 0 : 1f);
ObjectAnimator translationX2 = ObjectAnimator.ofFloat(rightView, "translationX", rightView.getTranslationX(), isShowNsv ? width : 0f);
AnimatorSet set2 = new AnimatorSet();
set2.playTogether(alpha2, translationX2); // 同步执行
set2.setDuration(duration);
set2.start();
}
}
2.com.android.launcher3.Launcher类添加两个方法
java
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(mLauncherView);
//在onCreate方法的最后-添加负一屏
setLauncherOverlay(ViewUtils.addNegativeScreen(this, (ViewGroup) mLauncherView));
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
//负一屏和DragLayer手势监听处理
if(ViewUtils.setDispatchTouchEvent(this,(ViewGroup) mLauncherView,ev)){
return true;
}
return super.dispatchTouchEvent(ev);
}