我自定义了一个继承自RelativeLayout的布局,效果是向右滑动后,内部的控件会向右移出屏幕。左划后又移回屏幕。
现在的情况是,内部控件右划移出屏幕后,把应用切换回后台,再切换到前台,然后左划把内部控件移回屏幕,这时这些内部控件会不显示,但是它们的确存在在那里,并可以接收点击效果,点击后就会显示出来。
现在想要的效果是从回台回来后,把内部控件拖动回屏幕后,直接显示。应该需要怎么实现?我试过用invalidate()刷新,可是不起作用。
package com.leu.textapplication;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import android.widget.Scroller;
/**
* Created by Leu on 2016/10/8.
*/
public class ScrollRelativeLayout extends RelativeLayout implements View.OnTouchListener {
private Scroller mScroller;
private int mScreenWitdh;
//0表示隐藏,1表示显示
private int beginX;
private int distanceX;
private GestureDetector mGestureDetector;
public ScrollRelativeLayout(Context context) {
super(context);
initView(context);
}
public ScrollRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public ScrollRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
private void initView(Context context) {
//setFocusable(true);
//requestFocus();
//this.setLongClickable(true);
this.setOnTouchListener(this);
//setFocusable(true);
setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS);
mScroller = new Scroller(context);
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
mScreenWitdh = outMetrics.widthPixels;
mGestureDetector = new GestureDetector(context, new SimpleGestureListener());
mGestureDetector.setIsLongpressEnabled(true);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
beginX = (int) event.getX();
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
Log.d("ScrollRelativeLayout", "执行up");
Log.d("ScrollRelativeLayout", "distanceX:" + distanceX);
distanceX = (int) event.getX() - beginX;
//右划
if (distanceX > 0) {
//右划超过固定距离
if (distanceX > 200) {
scrollRight();
//右划未超过固定距离
} else {
scrollLeft();
}
//左划
} else if(distanceX<0){
//左划超过固定距离
if (distanceX < -200) {
scrollLeft();
//左划未超过固定距离
} else {
scrollRight();
}
}
//通知View进行重绘,从而调用computeScroll的模拟过程
invalidate();
break;
}
return true;
}
private class SimpleGestureListener extends
GestureDetector.SimpleOnGestureListener {
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
//在主屏幕时,才能进行拖动。
if (getScrollX() + distanceX <= 0 && getScrollX() + distanceX > -mScreenWitdh) {
scrollBy((int) distanceX, 0);
}
return false;
}
//当执行onFling后,onTouchEvent的up动作不会再执行。
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
Log.d("ScrollRelativeLayout", "执行fling");
if (e1.getX() - e2.getX() > 0 && getScrollX() <= 0 && getScrollX() > -mScreenWitdh) {
//左划
scrollLeft();
} else if (e2.getX() - e1.getX() > 0 && getScrollX() <= 0 && getScrollX() > -mScreenWitdh) {
//右划
scrollRight();
}
invalidate();
return true;
}
}
/**
* 左划进屏幕
*/
private void scrollLeft() {
mScroller.startScroll(
getScrollX(),
0,
-getScrollX(),
0);
}
/**
* 右划出屏幕
*/
private void scrollRight() {
mScroller.startScroll(
getScrollX(),
0,
-(mScreenWitdh + getScrollX()),
0);
}
/**
* 重写computeScroll方法,实现模拟滑动
* 系统在绘制View的时候会在draw方法中调用该方法
*/
@Override
public void computeScroll() {
super.computeScroll();
// 判断Scroller是否执行完毕,是否完成了整个滑动
//当模拟过程结束后,该方法会返回false,从而中断循环,完成整个平滑移动过程。
if (mScroller.computeScrollOffset()) {
//通过不断地瞬间移动一个小的距离来实现整体上的平滑移动效果
scrollTo(
mScroller.getCurrX(),//获得当前的滑动坐标
mScroller.getCurrY());
// 通过重绘来不断调用computeScroll,通过invalidate→draw→computeScroll来间接调用。
invalidate();
}
}
}
Ask and answer your own questions. . .
Just put an empty full-screen View in the outermost layer to solve this problem. . . I don’t know why
This is because the Scroller only moves the content of the control (equivalent to the view), and the control itself does not actually move. This is like view animation. You can try using property animation to move by changing the translationX translationY properties.