转载请注明出处:http://blog.csdn.net/footballclub/
介绍
如果项目中遇到了侧滑的需求,主流的做法有两个用android自带的drawerlayout和slidingmenu,
因为之前项目中有播放视频的时候滑动菜单就会出现滑动卡顿和闪白的问题,所以个人不推荐slidingmenu;drawerlayout效果可以,但是不一定能符合产品UI设计的要求,因此能自己写侧滑就显得至关重要了。
效果图
从效果图上看,左边的是菜单,右边的是内容区域。菜单是一个包含listview的fragment,内容区域从上往下分别是toolbar,IntegrateFolderTitleStrip,viewpager。当菜单显示的时候,可以看到在内容区域的左边有个阴影的效果。以上就是今天要实现的效果。
原理图解
1.在初始状态菜单是完全隐藏的,所以这时候的布局就是这样
先说明下,黑色框是整个屏幕显示的区域,橙色的框是菜单区域,红色的框是内容区域。
此时,内容区域是把菜单区域完全盖着的,所以我们看不到菜单。
2.当菜单完全打开的时候,内容区域往右边滑动,滑至菜单的右侧,此时内容区域只是部分可见
由上面两幅图,我们能够想到的是,菜单是一个view,内容区域也是view,然后还需要有个容器来放置菜单和内容区域,那么这个容器肯定是viewgroup了,但是如果直接继承自viewgroup的话,我们还得重写它的onLayout方法,所以为了简单就直接继承RelativeLayout了。把view的测量和布局都交给RelativeLayout来做,我们只关注侧滑实现就行了。
开始动手
上面说了我们需要一个RelativeLayout来盛放菜单和内容。
XMenu.java
public class XMenu extends RelativeLayout {
private MenuView mMenuView;
private ContentView mContentView;
public XMenu(Context context) {
this(context, null);
}
public XMenu(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public XMenu(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
LayoutParams behindParams = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
mMenuView = new MenuView(context);
addView(mMenuView, behindParams);
LayoutParams aboveParams = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
mContentView = new ContentView(context);
addView(mContentView, aboveParams);
}
public void setMenu(int layoutId) {
setMenu(LayoutInflater.from(getContext()).inflate(layoutId, null));
}
public void setMenu(View v) {
mMenuView.setView(v);
}
public void setContent(int layoutId) {
setContent(LayoutInflater.from(getContext()).inflate(layoutId, null));
}
public void setContent(View v) {
mContentView.setView(v);
}
}
很简单的代码,我们先创建了MenuView和ContentView,分别是为了盛放menu和content的,然后分别加入XMenu中,再对外界提供设置menu和content的方法。接下来再分别实现MenuView和ContentView。
MenuView.java
public class MenuView extends ViewGroup {
private int menuWidth = 400;
public MenuView(Context context) {
super(context);
}
public MenuView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MenuView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = getDefaultSize(0, widthMeasureSpec);
int height = getDefaultSize(0, heightMeasureSpec);
setMeasuredDimension(width, height);
final int menuWidthSpec = getChildMeasureSpec(widthMeasureSpec, 0,
this.menuWidth);
final int menuHeightSpec = getChildMeasureSpec(heightMeasureSpec, 0,
height);
final int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
if(child.getVisibility()!=GONE){
child.measure(menuWidthSpec, menuHeightSpec);
}
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
if(child.getVisibility()!=GONE){
child.layout(l,t,r,b);
}
}
}
public void setMenuWidth(int menuWidth) {
this.menuWidth = menuWidth;
}
public void setView(View v) {
if (getChildCount() > 0) {
removeAllViews();
}
addView(