如下图是侧滑的效果图 实现的功能主要是用ViewDragHelper,用ViewDragHelper来自 ...
如下图是侧滑的效果图
实现的功能主要是用ViewDragHelper,用ViewDragHelper来自定义一个侧滑面板来实现侧滑
如下是自定义的侧滑面板
1 package com.demo.sb.widget; 2 3 import com.nineoldandroids.view.ViewHelper; 4 5 import android.content.Context; 6 import android.graphics.Color; 7 import android.graphics.PorterDuff.Mode; 8 import android.support.v4.view.ViewCompat; 9 import android.support.v4.widget.ViewDragHelper; 10 import android.util.AttributeSet; 11 import android.util.Log; 12 import android.view.MotionEvent; 13 import android.view.View; 14 import android.view.ViewGroup; 15 import android.widget.FrameLayout; 16 17 /** 18 * 侧滑面板 19 * 20 * @author Administrator 21 * 22 */ 23 public class DragLayout extends FrameLayout { 24 25 private ViewDragHelper mDragHelper; 26 private ViewGroup mLeftContent; 27 private ViewGroup mMainContent; 28 29 private Status mStatus = Status.Close; 30 private OnDragStatusChangeListener mListener; 31 32 /** 33 * 状态枚举 34 */ 35 public static enum Status { 36 Close, Open, Draging; 37 } 38 39 public interface OnDragStatusChangeListener { 40 void onClose(); 41 42 void onOpen(); 43 44 void onDraging(float percent); 45 } 46 47 public Status getStatus() { 48 return mStatus; 49 } 50 51 public void setStatus(Status mStatus) { 52 this.mStatus = mStatus; 53 } 54 55 public void setDragStatusListener(OnDragStatusChangeListener mListener) { 56 this.mListener = mListener; 57 } 58 59 public DragLayout(Context context) { 60 this(context, null); 61 // TODO Auto-generated constructor stub 62 } 63 64 public DragLayout(Context context, AttributeSet attrs) { 65 this(context, attrs, 0); 66 // TODO Auto-generated constructor stub 67 } 68 69 public DragLayout(Context context, AttributeSet attrs, int defStyle) { 70 super(context, attrs, defStyle); 71 // TODO Auto-generated constructor stub 72 /** 73 * a . 初始化(通过静态的方法) 74 */ 75 mDragHelper = ViewDragHelper.create(this, mCallback); 76 } 77 78 /** 79 * c. 重写Callback的事件 80 */ 81 ViewDragHelper.Callback mCallback = new ViewDragHelper.Callback() { 82 /** 83 * 1. 根据返回结果决定当前的child是否可以拖拽 child 当前被拖拽的View pointerId 区分多点触摸的id 84 */ 85 @Override 86 public boolean tryCaptureView(View child, int pointerId) { 87 Log.d("jiejie", "tryCaptureView: " + child); 88 return true;// 都可以尝试被拖拽 89 // return child == mMainContent;//只有主程序的View可以被拖拽 90 } 91 92 public void onViewCaptured(View capturedChild, int activePointerId) { 93 // 当capturedChild被捕获时,调用 94 Log.d("jiejie", "onViewCaptured: " + capturedChild); 95 } 96 97 public int getViewHorizontalDragRange(View child) { 98 // 返回拖拽的范围,不对拖拽进行真正的限制。仅仅决定了动画的执行速度 99 return mRange;100 }101 102 /**103 * 2. 根据建议值 修正将要移动到的(横向)位置(重要) 此时还没有真正移动104 */105 public int clampViewPositionHorizontal(View child, int left, int dx) {106 Log.d("jiejie", "clampViewPositionHorizontal: " + left);107 if (child == mMainContent) {108 left = fixLeft(left);109 }110 return left;111 }112 113 /**114 * 3. 当View位置改变的时候,处理要做的事情(更新状态, 伴随动画, 重绘界面) 此时,View已经发生了位置的改变115 * changedView 改变位置的View left 新的左边值 dx 水平方向变化量116 */117 public void onViewPositionChanged(View changedView, int left, int top,118 int dx, int dy) {119 super.onViewPositionChanged(changedView, left, top, dx, dy);120 Log.d("jiejie", "onViewPositionChanged: " + "left:" + left121 + " dx: " + dx);122 int newLeft = left;123 if (changedView == mLeftContent) {124 // 把当前变化量专递给mMainContent125 newLeft = mMainContent.getLeft() + dx;126 }127 // 进行修正128 newLeft = fixLeft(newLeft);129 130 if (changedView == mLeftContent) {131 // 当左面板移动之后,再强制放回去132 mLeftContent.layout(0, 0, 0 + mWidth, 0 + mHeight);133 mMainContent.layout(newLeft, 0, newLeft + mWidth, 0 + mHeight);134 }135 136 /**137 * 更新状态时设置动画(也可以不设置,不设置的话则默认平滑的状态,也可以省很多代码) 设置左面板和主面板,背景的动画138 */139 dispatchDragEvent(newLeft);140 141 // 为了兼容低版本,每次修改值之后,进行重绘142 invalidate();143 }144 145 /**146 * 4. 当View被释放的时候,处理的事情(执行动画) View releasedChild 被释放的子View float xvel147 * 水平方向的速度,向右为正 float yvel 竖直方向的速度, 向下为正148 */149 public void onViewReleased(View releasedChild, float xvel, float yvel) {150 Log.d("jiejie", "onViewReleased: " + "xvel: " + xvel + "yvel: "151 + yvel);152 super.onViewReleased(releasedChild, xvel, yvel);153 // 判断执行 关闭/开启154 // 先考虑所有开启的情况,剩下的就是都是关闭的情况155 if (xvel == 0 && mMainContent.getLeft() > (mRange / 2.0f)) {156 open();157 } else if (xvel > 0) {158 open();159 } else {160 chose();161 }162 }163 164 public void onViewDragStateChanged(int state) {165 super.onViewDragStateChanged(state);166 }167 };168 169 /**170 * 根据范围修正左边值171 * 172 * @param left173 * @return174 */175 private int fixLeft(int left) {176 if (left < 0) {177 return 0;178 } else if (left > mRange) {179 return mRange;180 }181 return left;182 }183 184 /**185 * 执行动画186 * 187 * @param newLeft188 */189 protected void dispatchDragEvent(int newLeft) {190 // TODO Auto-generated method stub191 float percent = newLeft * 1.0f / mRange;192 Log.d("jiejie", "percent: " + percent);193 if (mListener != null) {194 mListener.onDraging(percent);195 }196 197 // 更新状态,执行回调198 Status preStatus = mStatus;199 mStatus = updateStatus(percent);200 201 if (mStatus != preStatus) {202 // 状态发生变化203 if (mStatus == Status.Close) {204 // 当前变为关闭状态205 if (mListener != null) {206 mListener.onClose();207 }208 } else if (mStatus == Status.Open) {209 if (mListener != null) {210 mListener.onOpen();211 }212 }213 }214 215 // 伴随动画216 animViews(percent);217 }218 219 private Status updateStatus(float percent) {220 if (percent == 0f) {221 return Status.Close;222 } else if (percent == 1.0f) {223 return Status.Open;224 }225 return Status.Draging;226 }227 228 private void animViews(float percent) {229 // TODO Auto-generated method stub230 /**231 * >1.左面板:缩放动画,平移动画,透明度动画 缩放动画0.0 - > 1.0 >> 0.5f -> 1.0f >>>232 * 0.5f*percent+0.5f mLeftContent.setScaleX(0.5f + 0.5f * percent);233 * mLeftContent.setScaleY(0.5f + 0.5f * percent);234 */235 // mLeftContent.setScaleY(0.5f + 0.5f * percent);236 // mLeftContent.setScaleX(0.5f + 0.5f * percent);237 ViewHelper.setScaleX(mLeftContent, evaluate(percent, 0.5f, 1.0f));238 ViewHelper.setScaleY(mLeftContent, 0.5f + 0.5f * percent);239 // 平移动画:-mWidth / 2.0 f - > 0.0f240 ViewHelper.setTranslationX(mLeftContent,241 evaluate(percent, -mWidth / 2.0f, 0));242 // 透明度: 0.5 -> 1.0f243 ViewHelper.setAlpha(mLeftContent, evaluate(percent, 0.5f, 1.0f));244 245 /**246 * >2. 主面板:缩放动画247 */248 // 1.0f -> 0.8f249 ViewHelper.setScaleX(mMainContent, evaluate(percent, 1.0f, 0.8f));250 ViewHelper.setScaleY(mMainContent, evaluate(percent, 1.0f, 0.8f));251 252 /**253 * >3. 背景动画: 亮度变化(颜色变化)254 */255 getBackground()256 .setColorFilter(257 (Integer) evaluateColor(percent, Color.BLACK,258 Color.TRANSPARENT), Mode.SRC_OVER);259 }260 261 /**262 * 估值器263 * 264 * @param fraction265 * @param startValue266 * @param endValue267 * @return268 */269 public Float evaluate(float fraction, Number startValue, Number endValue) {270 float startFloat = startValue.floatValue();271 return startFloat + fraction * (endValue.floatValue() - startFloat);272 }273 274 /**275 * 颜色变化过度276 * 277 * @param fraction278 * @param startValue279 * @param endValue280 * @return281 */282 public Object evaluateColor(float fraction, Object startValue,283 Object endValue) {284 int startInt = (Integer) startValue;285 int startA = (startInt >> 24) & 0xff;286 int startR = (startInt >> 16) & 0xff;287 int startG = (startInt >> 8) & 0xff;288 int startB = startInt & 0xff;289 290 int endInt = (Integer) endValue;291 int endA = (endInt >> 24) & 0xff;292 int endR = (endInt >> 16) & 0xff;293 int endG = (endInt >> 8) & 0xff;294 int endB = endInt & 0xff;295 296 return (int) ((startA + (int) (fraction * (endA - startA))) << 24)297 | (int) ((startR + (int) (fraction * (endR - startR))) << 16)298 | (int) ((startG + (int) (fraction * (endG - startG))) << 8)299 | (int) ((startB + (int) (fraction * (endB - startB))));300 }301 302 @Override303 public void computeScroll() {304 // TODO Auto-generated method stub305 super.computeScroll();306 // 2. 持续平滑动画(高频率调用)307 if (mDragHelper.continueSettling(true)) {308 // 如果返回true,动画还需要继续执行309 ViewCompat.postInvalidateOnAnimation(this);310 }311 }312 313 // public void chose() {314 // // TODO Auto-generated method stub315 // chose(true);316 // }317 public void chose() {318 // TODO Auto-generated method stub319 chose(true);320 }321 322 /**323 * 关闭324 * 325 * @param b326 */327 public void chose(boolean isSmooth) {328 // TODO Auto-generated method stub329 int finalLeft = 0;330 // 1. 触发一个平滑动画331 if (isSmooth) {332 if (mDragHelper.smoothSlideViewTo(mMainContent, finalLeft, 0)) {333 // 返回true代表还没有移动到指定位置,需要刷新界面334 // 参数传this(child所在的ViewGroup)335 ViewCompat.postInvalidateOnAnimation(this);336 }337 } else {338 mMainContent.layout(finalLeft, 0, finalLeft + mWidth, 0 + mHeight);339 }340 }341 342 public void open() {343 // TODO Auto-generated method stub344 open(true);345 }346 347 /**348 * 开启349 * 350 * @param b351 */352 public void open(boolean isSmooth) {353 // TODO Auto-generated method stub354 int finalLeft = mRange;355 if (isSmooth) {356 // 1. 触发一个平滑动画357 if (mDragHelper.smoothSlideViewTo(mMainContent, finalLeft, 0)) {358 // 返回true代表还没有移动到指定位置,需要刷新界面359 // 参数this(child所在的ViewGroup)360 ViewCompat.postInvalidateOnAnimation(this);361 }362 } else {363 mMainContent.layout(finalLeft, 0, finalLeft + mWidth, 0 + mHeight);364 }365 }366 367 /**368 * b. 专递触摸事件369 */370 public boolean onInterceptTouchEvent(MotionEvent ev) {371 // 传递给mDragHandler372 return mDragHelper.shouldInterceptTouchEvent(ev);373 };374 375 @Override376 public boolean onTouchEvent(MotionEvent event) {377 // TODO Auto-generated method stub378 try {379 mDragHelper.processTouchEvent(event);380 } catch (Exception e) {381 e.printStackTrace();382 }383 // 返回true,持续接收事件384 return true;385 }386 387 /**388 * 当View中所有的子控件 均被映射成389 */390 @Override391 protected void onFinishInflate() {392 // TODO Auto-generated method stub393 super.onFinishInflate();394 if (getChildCount() < 2) {395 throw new IllegalAccessError(396 "布局至少有2个孩子. Your ViewGroup must have 2 children at least");397 }398 if (!(getChildAt(0) instanceof ViewGroup && getChildAt(1) instanceof ViewGroup)) {399 throw new IllegalArgumentException(400 "子View必须是ViewGroup的子类. Your children must be an instance of ViewGroup");401 }402 mLeftContent = (ViewGroup) getChildAt(0);403 mMainContent = (ViewGroup) getChildAt(1);404 }405 406 /**407 * 当view的大小发生变化时触发408 */409 private int mRange;410 private int mHeight;411 private int mWidth;412 413 @Override414 protected void onSizeChanged(int w, int h, int oldw, int oldh) {415 // 当尺寸有变化的时候调用416 super.onSizeChanged(w, h, oldw, oldh);417 mHeight = getMeasuredHeight();418 mWidth = getMeasuredWidth();419 mRange = (int) (mWidth * 0.6f);420 }421 422 }
海外公司注册、海外银行开户、跨境平台代入驻、VAT、EPR等知识和在线办理:https://www.xlkjsw.com
原标题:侧滑2
关键词:
*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们:
admin#shaoqun.com
(#换成@)。