效果图
代码分析
这次代码放在demo中直接下载即可,这里理一下思路
1.activity上是一个帧布局,覆盖着两层view
底下一层view是list列表,就是上图灰色部分,还有一层是一个自定义的水平scrollview,这个view中左侧是是一个透明的view,右侧是上图白色的那个view。滚动就是水平scrollview滚动。
2.由于有view覆盖的关系,就涉及touch事件处理
activity中onCreate代码
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
inflater = LayoutInflater.from(this);
setContentView(inflater.inflate(R.layout.menu_scroll_view, null));
scrollView = (MenuHorizontalScrollView) findViewById(R.id.mScrollView);
menuList = (ListView) findViewById(R.id.menuList);
acbuwaPage = inflater.inflate(R.layout.acbuwa_page, null);
menuBtn = (Button) this.acbuwaPage.findViewById(R.id.menuBtn);
//按钮添加处理
menuBtn.setOnClickListener(onClickListener);
//这里定义一个透明的view
View leftView = new View(this);
leftView.setBackgroundColor(Color.TRANSPARENT);
//
children = new View[] { leftView, acbuwaPage };
//初始化
scrollView.initViews(children, new SizeCallBackForMenu(this.menuBtn),
this.menuList);
scrollView.setMenuBtn(this.menuBtn);
}
leftView为一个透明的view,这里一定会有人问在哪控制这个透明view的宽度呢,请看源码中的MenuHorizontalScrollView类
/****************************************************/
/*- -*/
/*- Class Area -*/
/*- -*/
/****************************************************/
public class MenuOnGlobalLayoutListener implements OnGlobalLayoutListener
{
private ViewGroup parent;
private View[] children;
// private int scrollToViewIndex = 0;
private SizeCallBack sizeCallBack;
public MenuOnGlobalLayoutListener(ViewGroup parent, View[] children, SizeCallBack sizeCallBack)
{
this.parent= parent;
this.children= children;
this.sizeCallBack= sizeCallBack;
}
//视图树的可视性或全局布局状态发生变化时执行的回调函数
@Override
public void onGlobalLayout()
{
// TODO Auto-generated method stub
me.getViewTreeObserver().removeGlobalOnLayoutListener(this);
this.sizeCallBack.onGlobalLayout();
this.parent.removeViewsInLayout(0, children.length);
int width= me.getMeasuredWidth();
int height= me.getMeasuredHeight();
int[] dims= new int[2];
scrollToViewPos= 0;
for (int i= 0; i < children.length; i++)
{
this.sizeCallBack.getViewSize(i, width, height, dims);
children[i].setVisibility(View.VISIBLE);
parent.addView(children[i], dims[0], dims[1]);
if (i == 0)
{
scrollToViewPos+= dims[0];
}
}
// if(firstLoad){
new Handler().post(new Runnable()
{
@Override
public void run()
{
me.scrollBy(scrollToViewPos, 0);
/* 视图不是中间视图 */
me.setVisibility(View.VISIBLE);
menu.setVisibility(View.VISIBLE);
}
});
// }
}
}
OnGlobalLayoutListener 的介绍
view的时间传递机制介绍
http://blog.csdn.net/wong_judy/article/details/5192777
http://www.cnblogs.com/jqyp/archive/2012/04/25/2469758.html
在demo中SlidingLinearLayout类中
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
this.lastMotionX = (int) ev.getRawX();
}
if (this.lastMotionX < 20)
return true;
else if (MenuHorizontalScrollView.menuOut)
return true;
else
return super.onInterceptTouchEvent(ev);
}
这里控制在menu弹出时,主界面不响应touch事件,menu关闭时,主界面左侧20像素内touch可滑动界面,这里你可以把响应区调大或调小
一点变化
这个demo菜单menu是放在activity下层的view中的,效果是上层界面覆盖的效果,也可以把菜单view放到左侧的透明view中,效果就是菜单拉出的效果,这么改的话,事件处理会简单一点。
demo地址
http://download.csdn.net/detail/shix_foot/5166926
2013-4-28补充
如何现实menu元素右对齐?
menu设置的宽度是全屏,要是想让menu中的控件相对主界面划开部分右对齐的话,直接设置边距并不好用。换个分辨率的屏幕就不好使了。
对上面的demo做一些修改,实现效果如下:
图中的“3”相对右侧界面的距离是固定的,换分辨率的手机也是一样,不会出现文字被覆盖或者过远的情况。
我实现的方法是如下:
1.在menulist所在的LinearLayout中再嵌套一个LinearLayout(menuhead),宽度设为wrap_content,初始化时设为static;
2.在SizeCallBackForMenu方法中添加宽度的设置,代码如下
if(idx != 1){
dims[0] = width - this.menuWidth;
//动态设置view的宽度
LayoutParams lp;
lp=(LayoutParams) NewShop2Activity.menuhead.getLayoutParams();
lp.width=dims[0];//getMeasuredWidth
lp.height=LayoutParams.WRAP_CONTENT;
NewShop2Activity.menuhead.setLayoutParams(lp);
}
思路就是根据侧拉的宽度动态的计算menulist显示部分的宽度,目前效果还可以,没出现问题。
2013-5-15 github上基于Fragment侧滑导航,效果非常好
https://play.google.com/store/apps/details?id=com.slidingmenu.example
神一下的demo。。由于关联了ActionBarSherlock
所以你还需要把https://github.com/JakeWharton/ActionBarSherlock下好,我这边关联好之后就可以使用了,很赞