QQ5.0 侧滑栏效果
标签: Android 侧滑
我看见挺多APP采用的是这种一滑整个界面都向右移的方式。
这里采用的是 HorizontalScrollView(水平滑动视图) 布局的滑动特性。
就是两个界面放在一起,实现界面的滑动
先是布局界面
<?xml version="1.0" encoding="utf-8"?>
<com.example.myslidingmenu.MySlidingMenu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns="http://schemas.android.com/tools"
xmlns:zhy="http://schemas.android.com/apk/com.example.myslidingmenu"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:scrollbars="none"
zhy:rightPadding="100dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="horizontal">
<ListView
android:id="@+id/list_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#45f78f"
android:listSelector="?attr/selectableItemBackground"
xmlns:android="http://schemas.android.com/apk/res/android">
</ListView>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#123345">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="this is one "
android:textSize="30sp"/>
</LinearLayout>
</LinearLayout>
</com.example.myslidingmenu.MySlidingMenu>
就放了两个东西一个是ListView,另一个是TextView。
接下来是自定义MySlidingMenu的具体代码:
/**
* Created by hero on 2015/12/27.
*/
public class MySlidingMenu extends HorizontalScrollView {
//屏幕宽度
private int mScreemWidth;
//
private int mMenuRightPending;
/**
* 菜单宽度
*/
private int mMenuWidth;
private int mHalfMenuWidth;
private boolean once ;
/**
*
* @param context
* @param attrs
*/
public MySlidingMenu(Context context, AttributeSet attrs) {
super(context, attrs);
mScreemWidth = getScreemWidth(context); //获得屏幕宽度
}
/**
* 获取屏幕宽度的方法
* @param context
* @return
*/
private int getScreemWidth(Context context){
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display mDisplay = manager.getDefaultDisplay();
Point mPoint = new Point();
mDisplay.getSize(mPoint);
return mPoint.x;
}
public MySlidingMenu(Context context,AttributeSet attr,int defStyle){
super(context,attr,defStyle);
mScreemWidth = getScreemWidth(context); //获得屏幕宽度
//从布局文件中获得自定义属性(不是很懂)
TypedArray a = context.getTheme().obtainStyledAttributes(attr,R.styleable.MySlidingMenu,defStyle,0);
int n = a.getIndexCount();
for (int i =0;i<n;i++){
int mAttr = a.getIndex(i);
switch (mAttr){
case R.styleable.MySlidingMenu_rightPadding:
mMenuRightPending = a.getDimensionPixelSize(mAttr,(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,50f,getResources().getDisplayMetrics()));
}
}
a.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (!once){
LinearLayout wrapper = (LinearLayout) getChildAt(0);
ViewGroup menu = (ViewGroup) wrapper.getChildAt(0); //布局中的第一个容器从左到右,即侧滑菜单是第一个
ViewGroup content = (ViewGroup) wrapper.getChildAt(1); //布局中的第二个容器,即主界面。
//dp to px
// mMenuRightPending = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,mMenuRightPending,content.getResources().getDisplayMetrics());
// mMenuRightPending = 900;
mMenuRightPending = mScreemWidth*2/3;
mMenuWidth = mScreemWidth - mMenuRightPending; //侧滑出的菜单的宽度
mHalfMenuWidth = mMenuWidth/2; //菜单宽度的一半用于触摸判断
menu.getLayoutParams().width = mMenuWidth; //设置菜单宽度
content.getLayoutParams().width = mScreemWidth;//设置主界面宽度
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//初始化时调用
//onMeasure
//onLayout(再次调用了onMeasure)
//onMeasure
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
//第一次建立时调用
if (changed){
//将菜单隐藏
Log.d("onLayout","scrollTo");
this.scrollTo(mMenuWidth,0);
once = true;
}
}
/**
* 触控行为时调用
* @param ev
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
//判断滑动类型
switch (action){
case MotionEvent.ACTION_UP:
/**
* scrollx 当前VIEW相对原点(母容器最左端)的距离
* 母容器全长mScreemWidth=1440,侧栏隐藏时scrollx=480,既
* mMenuRightPending = mScreemWidth*2/3;
* mMenuWidth = mScreemWidth - mMenuRightPending; //侧滑出的菜单的宽度
*
*/
int scrollx = getScrollX();
if (scrollx>mHalfMenuWidth){
this.smoothScrollTo(mMenuWidth,0);
Log.d("onTouchEvent", mScreemWidth+"smoothScrollTo(mMenuWidth,0)"+scrollx);
}else{
/**
* smoothScrollTo(x,y) 相对原点的距离(母容器最左端)
* 0,0既从母容器最左端显示
*/
this.smoothScrollTo(0,0); //显示侧边
Log.d("onTouchEvent", mScreemWidth+"smoothScrollTo(0,0)"+scrollx);
}
return true;
}
return super.onTouchEvent(ev);
}
}
核心部分:
smoothScrollTo(0,0);
X轴,Y轴偏移量为0,界面显示从最左边开始
偏移量相对于母容器即MySlidingMenu左上顶点int scrollx = getScrollX();
/**
* scrollx 当前VIEW相对原点(母容器最左端)的距离
* 母容器全长mScreemWidth=1440,侧栏隐藏时scrollx=480,既
* mMenuRightPending = mScreemWidth*2/3;
* mMenuWidth = mScreemWidth - mMenuRightPending; //侧滑出的菜单的宽度
*
*/
使用app:layout_behavior属性时gradel文件要添加下面一句话
compile 'com.android.support:design:23.0.0'
侧滑时实现菜单在界面后
QQ5.0的样式并不是这么简单的一拉就出来,需要添加点动画。
在我们滑动的时候,菜单应该像是在界面的后面
那就相当于不断的改变菜单的位置,让它一直处于屏幕的左边。
就重写了一个方法
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
//获得一个比例1-0
//菜单不显示是为1,显示时为0
float p = l*1.0f/menuWidth;
menu.setTranslationX((float) (0.85*menuWidth*p));
}
界面发生更改时执行。
menu.setTranslationX((float) (0.7*menuWidth*p));
不断改变菜单的位置实现效果。
同时也可以改变宽度和高度,同时实现缩放。
这里有一个重点:
HorizontalScrollView中两个VIEW发生重叠时其中一个VIEW重叠部分不显示。