转载请注明出处:From李诗雨---http://blog.csdn.net/cjm2484836553/article/details/71063040
不诗意的女程序猿不是好厨师~
在前面的自定义View一、二、三 三篇文章中,我们基本涉及到了关于自定义View的所有知识点。基础有了,重点看了,难点沾了,思路也明朗了。那我们不来动手写写,是不是觉得太过分了?所以今天我们就先来实现一个简易的侧滑菜单吧,真的是超简单。
先看一下今天我们要完成的简易侧滑菜单效果的效果。
功能概括:
可以通过左右滑动对菜单进行拖拽,
可以通过点击具体的按键实现菜单的自动打开与关闭。
现在,就让我们完全按照第三篇文章整理出来的思路来一步一步进行:
这里我们继承FrameLayout
public class MySlideLayout extends FrameLayout {
public MySlideLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
这里我们不需要,所以略过即可~
3.1 重写onFinishInflate()方法,来得到菜单视图。这里我们默认第二个孩子是侧滑菜单。
@Override
protected void onFinishInflate() {
super.onFinishInflate();
menuView = getChildAt(1);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
menuWidth = menuView.getMeasuredWidth();
menuHeight = menuView.getMeasuredHeight();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
menuView.layout(-menuWidth, 0, 0, menuHeight);
}
这里我们需要实现可拖动的菜单,所以是涉及到滑动的。
所以我们需要
4.1 重写onTouchEvent()方法来响应用户的操作:
在move时来计算事件的偏移, 对当前布局进行滚动
在up时, 根据布局来的偏移量, 来判断是打开/关闭菜单
@Override
public boolean onTouchEvent(MotionEvent event) {
int eventX = (int) event.getRawX();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN :
lastX = eventX;
break;
case MotionEvent.ACTION_MOVE :
int dx = eventX-lastX;
int scrollX = getScrollX()-dx;
//限制scrollX : [-menuWidth, 0]
if(scrollX<-menuWidth) {
scrollX = -menuWidth;
} else if(scrollX>0) {
scrollX = 0;
}
scrollTo(scrollX, getScrollY());
lastX = eventX;
break;
case MotionEvent.ACTION_UP :
//得到布局的偏移量
int totalScrollX = getScrollX();
if(totalScrollX<=-menuWidth/2) {
openMenu();
} else {
closeMenu();
}
break;
}
return true;
}
4.2.1 平滑的打开菜单
private void openMenu() {
scroller.startScroll(getScrollX(), getScrollY(), -menuWidth-getScrollX(), -getScrollY());
invalidate();
isOpen = true;
}
4.2.2 平滑的关闭菜单
private void closeMenu() {
scroller.startScroll(getScrollX(), getScrollY(), -getScrollX(), -getScrollY());
invalidate();
isOpen = false;
}
Scroller本身是无法让View弹性滑动的,它需要和View的computeScroll方法配合使用才能共同完成
所以这里我们还需要重写computeScroll()方法
@Override
public void computeScroll() {
super.computeScroll();
if(scroller.computeScrollOffset()) {
scrollTo(scroller.getCurrX(), scroller.getCurrY());
invalidate();
}
}
4.4 最后我们再提供一个可以切换状态的方法,以方便外界调用
public void switchState() {
if (isOpen) {
closeMenu();
} else {
openMenu();
}
}
暂时还不涉及,暂不考虑~
经过以上简单几步,我们的自定义View就基本完成了,接下来就可以开始使用了。
MainActivity的布局中使用自定义View:
详细布局见源码
MainActivity的代码:
public class MainActivity extends AppCompatActivity {
private TextView tv_answer;
private MySlideLayout ml_main;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_answer = (TextView) findViewById(R.id.tv_answer);
ml_main = (MySlideLayout) findViewById(R.id.ml_main);
//点击图标切换打开、关闭的状态
findViewById(R.id.main_back).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ml_main.switchState();
}
});
}
//点击左侧item的点击事件的响应
public void clickMenuItem(View v) {
TextView textiew = (TextView) v;
String answer = "抱歉,主人没有给出明确答案";
tv_answer.setText(answer);
ml_main.switchState();
}
}
这就行了?恩!这样一个简易的侧滑菜单就实现了。话说会不会太简单朴素了,你们是不是都不屑于下手了?
这个,别急,学习也要循序渐进的吗?后期还会有很多比较复杂的自定义View的实践的,奈何五一假期过完了,只能往后放放再增加新篇了。
源码下载:点击下载