activity实现滑动效果
16lz
2021-01-26
可滑动的activity
- 可滑动的activity原理,就是将activity的theme设置为透明,之后滑动view的parent即可
- 效果图
主题透明
android:theme="@android:style/Theme.Translucent.NoTitleBar"
之后自定义一个SwipLayout 继承FrameLayout
`public class SwipLayout extends FrameLayout {private View parent;public SwipLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); }public SwipLayout(Context context, AttributeSet attrs) { this(context, attrs,0); // TODO Auto-generated constructor stub}public SwipLayout(Context context) { this(context,null);}`
之后我们拿到swiplayout的parent。因为我们使用scrollto,因此应该对父容器进行滚动
`public void onWindowFocusChanged(boolean hasWindowFocus) { // 在界面可以和用户交互的时候 并且第一次的时候 才进行初始化 super.onWindowFocusChanged(hasWindowFocus); if(hasWindowFocus&&isFirst){ isFirst=false; init(); //拿到父容器 当window可见的时候 } } private void init() { parent = (View) getParent(); }
`
之后对相关事件进行拦截
`public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: curX = (int) ev.getRawX(); x=curX; break; case MotionEvent.ACTION_MOVE: int touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); if(ev.getRawX()-curX>touchSlop) { // Log.e("", "actionMove"); //小于触摸的范围就可以 if(ev.getRawX()<100) return true;//拦截 } break; } return super.onInterceptTouchEvent(ev); }`
- 一定要使用屏幕坐标,否则会造成卡顿,因为我们在拿view的坐标的时候,view的位置也在改变
在onTouchEvent中处理,拦截的事件即可
`public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: x = (int) event.getRawX();// 要拿到屏幕的坐标 break; case MotionEvent.ACTION_MOVE: int min=(int) (event.getRawX()-x); if(parent.getScrollX()<=0&&parent.getScrollX()>=-parent.getWidth()) {parent.scrollTo(Math.min(Math.max(parent.getScrollX()-min, -parent.getWidth()), 0), 0); x=(int) event.getRawX(); //一定获得屏幕的坐标 不要 相对坐标 否则会造成闪动 return true; } break; case MotionEvent.ACTION_UP: if(parent.getScrollX()<-parent.getWidth()/2){ //关闭 colse(); }else if(parent.getScrollX()>-parent.getWidth()/2){ //打开 open(); } break; } return super.onTouchEvent(event);}`
之后我们自定义了动画,完成关闭和开启
`class ScrollAnimation extends Animation{private int end;private int lenght;private int start;public ScrollAnimation(int end) { this.end = end; lenght=end-parent.getScrollX(); setDuration(Math.abs(lenght)/2); start=parent.getScrollX();}@Overrideprotected void applyTransformation(float interpolatedTime, Transformation t) { // 0--100 1s //interpolatedTime 比例 0f-1f super.applyTransformation(interpolatedTime, t); int path= (int) (interpolatedTime*lenght); int currentX=start+path; if(currentX>0)currentX=0; if(currentX<-parent.getWidth())currentX=-parent.getWidth(); parent.scrollTo(currentX, 0);}}`
activity滑出右侧时候,接口回调
`public interface onSwipCloseListener{public void onSwipClose();}public void setOnSwipCloseListener(onSwipCloseListener closeListener){ this.swipCloseListener=closeListener;}`
- swiplayout一定是顶层布局才生效
- 总结,滑动的activity本质就是修改contentView的父容器 也就是修改id为content的FragmentLayout的子view
源码如下
`package com.example.swiplayout;import android.app.Activity;import android.content.Context;import android.graphics.drawable.BitmapDrawable;import android.provider.ContactsContract.CommonDataKinds.Event;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.view.ViewConfiguration;import android.view.ViewGroup;import android.view.ViewParent;import android.view.ViewPropertyAnimator;import android.view.WindowManager;import android.widget.FrameLayout;import android.view.View.OnTouchListener;import android.view.animation.Animation;import android.view.animation.Animation.AnimationListener;import android.view.animation.Transformation;public class SwipLayout extends FrameLayout {private View parent;public SwipLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); }public SwipLayout(Context context, AttributeSet attrs) { this(context, attrs,0); // TODO Auto-generated constructor stub}public SwipLayout(Context context) { this(context,null);}private void init() { parent = (View) getParent();}@Overridepublic boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: x = (int) event.getRawX();// 要拿到屏幕的坐标 break; case MotionEvent.ACTION_MOVE: int min=(int) (event.getRawX()-x); if(parent.getScrollX()<=0&&parent.getScrollX()>=-parent.getWidth()) {parent.scrollTo(Math.min(Math.max(parent.getScrollX()-min, -parent.getWidth()), 0), 0); x=(int) event.getRawX(); //一定获得屏幕的坐标 不要 相对坐标 否则会造成闪动 return true; } break;case MotionEvent.ACTION_UP: if(parent.getScrollX()<-parent.getWidth()/2){ //关闭 colse(); }else if(parent.getScrollX()>-parent.getWidth()/2){ //打开 open(); } break;}return super.onTouchEvent(event);}private void colse() { ScrollAnimation closeAnimation=new ScrollAnimation(-parent.getWidth()); parent.startAnimation(closeAnimation); closeAnimation.setAnimationListener(new AnimationListenerAdapter(){ @Override public void onAnimationEnd(Animation animation) { // TODO Auto-generated method stub super.onAnimationEnd(animation); if(swipCloseListener!=null){ swipCloseListener.onSwipClose(); } } });}private void open() { ScrollAnimation open=new ScrollAnimation(0); parent.startAnimation(open);}boolean isFirst=true;private int x;@Overridepublic void onWindowFocusChanged(boolean hasWindowFocus) { // 在界面可以和用户交互的时候 并且第一次的时候 才进行初始化 super.onWindowFocusChanged(hasWindowFocus); if(hasWindowFocus&&isFirst){ isFirst=false; init(); //拿到父容器 当window可见的时候 }}class ScrollAnimation extends Animation{ private int end; private int lenght; private int start; public ScrollAnimation(int end) { this.end = end; lenght=end-parent.getScrollX(); setDuration(Math.abs(lenght)/2); start=parent.getScrollX(); } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { // 0--100 1s //interpolatedTime 比例 0f-1f super.applyTransformation(interpolatedTime, t); int path= (int) (interpolatedTime*lenght); int currentX=start+path; if(currentX>0)currentX=0; if(currentX<-parent.getWidth())currentX=-parent.getWidth(); parent.scrollTo(currentX, 0); }}private onSwipCloseListener swipCloseListener;private int curX;public interface onSwipCloseListener{ public void onSwipClose();}public void setOnSwipCloseListener(onSwipCloseListener closeListener){ this.swipCloseListener=closeListener;} //实现了一个animation适配器 class AnimationListenerAdapter implements AnimationListener{ @Override public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: curX = (int) ev.getRawX(); x=curX; break; case MotionEvent.ACTION_MOVE: int touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); if(ev.getRawX()-curX>touchSlop) { // Log.e("", "actionMove"); //小于触摸的范围就可以 if(ev.getRawX()<100) return true;//拦截 } break; } return super.onInterceptTouchEvent(ev); }}
`
更多相关文章
- Android(安卓)RecyclerView使用 及 滑动时加载图片优化方案
- android view事件分发机制
- Android(安卓)开发 设置banner圆角,滑动时,图片圆角失效
- UI控件--自定义SeekBar样式
- Android实现图片左右滑动效果
- Android(安卓)拦截Home键的常用方法
- Android(安卓)OpenGL 文本显示 LabelMaker
- 暂时只会这种导航,实时显示自己的位置,,求其他更好的方法,或api
- android开发之修改ListView默认滑动条样式