滑动面板张女士现在easy找到一个成熟的第三方框架,但是,我们自己做的事,写一些核心代码,帮助我们理解
1,简单的介绍
写一个类继承ViewGroup
复写下面三个方法
onMeasure -> onLayout -> onDraw
1。測量左面板和主面板
左面板宽是指定的值240, 高度是屏幕高度
主面板宽高就是屏幕的宽高
2,摆放两个子控件
左面板的位置: 当前屏幕左边界0, 往左-240
主面板位置 : 当前控件的位置
3。处理触摸事件 (左右移动两个控件)
按下时, 获取按下的坐标downX = 20
移动时,
获取当前最新x坐标 moveX = 30
计算要运行的偏移量 - (30 - 20) = -10
让偏移生效scrollBy(-10, 0)
moveX 赋值给 downX, 作为新的按下点
抬起时, 依据当前偏移位置, 运行动画 (运行平滑动画)
二,核心代码
/**
* 側滑面板
* @author poplar
*
*/
public class SlideMenu extends ViewGroup {
private final int MAIN_CONTENT = 0; // 主面板状态
private final int MENU_CONTENT = 1; // 左菜单状态
int currentState = MAIN_CONTENT; // 当前状态
private Scroller scroller;
private int downX; // 按下的X值坐标
private int downY; // 按下的Y值坐标
public SlideMenu(Context context) {
super(context);
init();
}
public SlideMenu(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SlideMenu(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
// 滚动模拟器
scroller = new Scroller(getContext());
// startX, x轴从什么位置開始滚动 -100
// startY, y轴从什么位置開始滚动
// dx, 从開始位置 到 目标位置的 偏移量 -100 -> 50
// 偏移量 150 = (50 - (-100))
// 偏移量 = (目标位置 x) - (開始位置x)
// dy,
// duration , 动画运行时长 dx * 10
// scroller.startScroll(startX, startY, dx, dy, duration);
}
/**
* 測量子控件
* widthMeasureSpec : 当前控件的宽度属性
* heightMeasureSpec : 当前控件的高度属性
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 获取到左面板
View leftMenu = getChildAt(0);
// 宽度自身宽度, 高度屏幕的高度
leftMenu.measure(leftMenu.getLayoutParams().width, heightMeasureSpec);
// 測量主面板
View main = getChildAt(1);
main.measure(widthMeasureSpec, heightMeasureSpec);
}
/**
* 摆放两个子控件
*
* left 控件左边界位置
* top 控件上边界位置
* right 控件右边界位置
* bottom 控件下边界位置
*
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// 摆放左面板
View leftMenu = getChildAt(0);
leftMenu.layout(0 - leftMenu.getMeasuredWidth(), 0, 0, b);
// 摆放主面板
View main = getChildAt(1);
main.layout(l, t, r, b);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 按下时的x坐标
downX = (int) event.getX();
break;
case MotionEvent.ACTION_MOVE:
// 移动后的x坐标
int moveX = (int) event.getX();
// 变化量
int scrollX = - (moveX - downX);
// ------------------------------------------------- 重点 ↓
// 计算变化后的位置
int newScrollX = getScrollX() + scrollX;
int leftLimit = -getChildAt(0).getMeasuredWidth();
if(newScrollX < leftLimit){
// < -240
scrollTo(leftLimit, 0);
} else if (newScrollX > 0) {
// >0 限定右边界
scrollTo(0, 0);
} else {
// 让变化量生效
scrollBy(scrollX, 0);
}
// ------------------------------------------------- 以上 ↑
//把上一个moveX赋值给downX
downX = moveX;
break;
case MotionEvent.ACTION_UP:
// 抬起时, 依据当前偏移位置, 运行动画
int leftMenuCenter = - getChildAt(0).getMeasuredWidth() / 2;
int currentScrollX = getScrollX();
System.out.println("currentScrollX: " + currentScrollX);
System.out.println("leftMenuCenter: " + leftMenuCenter);
if(currentScrollX > leftMenuCenter){
// 假设当前滚动的位置在一半的右边 , 显示主面板 , scrollX > leftMenuCenter
currentState = MAIN_CONTENT;
System.out.println("运行显示主面板动画");
updateCurrentContent();
}else {
// 假设当前滚动的位置在一半的左边 , 显示左菜单 , scrollX <= leftMenuCenter
currentState = MENU_CONTENT;
System.out.println("运行显示左菜单动画");
updateCurrentContent();
}
break;
default:
break;
}
return true;
}
private void updateCurrentContent() {
int scrollX = getScrollX();
int dx = 0;
if(currentState == MAIN_CONTENT){
// 运行动画,显示主面板
// scrollTo(0, 0);
// 目标值 - 当前值
dx = 0 - scrollX;
} else if(currentState == MENU_CONTENT){
// 运行动画,显示左菜单
// scrollTo(- getChildAt(0).getMeasuredWidth(), 0);
// 目标值 - 当前值
// - 240 -
dx = -getChildAt(0).getMeasuredWidth() - scrollX;
System.out.println("dx: " + dx + " scrollX: " + scrollX);
}
// ------------------------------------------------- 重点 ↓
// 開始模拟数据
scroller.startScroll(scrollX, 0, dx, 0, Math.abs(dx * 10));
// -100 -> -240 >> -150
// 使scroller模拟的数据生效
invalidate(); // drawChild -> child.draw( -> computeScroll
// ------------------------------------------------- 以上 ↑
}
// ------------------------------------------------- 重点 ↓
@Override
public void computeScroll() {
if(scroller.computeScrollOffset()){
// 动画还没运行完
// 得到当前模拟的数值
int currX = scroller.getCurrX();
scrollTo(currX, 0);
// System.out.println("currX: " + currX);
// 重绘界面, 递归调用
invalidate();
}
}
// ------------------------------------------------- 以上 ↑
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// 仅仅有在用户水平滑动的时候才拦截
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = (int) ev.getX();
downY = (int) ev.getY();
break;
case MotionEvent.ACTION_MOVE:
int moveX = (int) ev.getX();
int moveY = (int) ev.getY();
int diffX = Math.abs(moveX - downX);
int diffY = Math.abs(moveY - downY);
if(diffX > diffY && diffX > 10){
return true;
}
break;
case MotionEvent.ACTION_UP:
break;
default:
break;
}
return super.onInterceptTouchEvent(ev);
}
}
版权声明:本文博主原创文章,博客,未经同意不得转载。
转载于:https://www.cnblogs.com/bhlsheji/p/4917193.html
相关资源:android仿优酷菜单 底部半圆滑出