最近学App的时候经常会用到侧滑的效果,所以对学习到的方法进行一个总结
1.普通Sliding
在activity_main.xml利用Android自带的HorizontalScrollView实现(里面只允许放一个控件)
以下是具体的代码
主布局 activity_main.xml 在LinearLayout里包含一个left_menu菜单模块和内容模块(这里为了简单些 所以只放了一张图片)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.view.SlidingMenu
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal" >
<include layout="@layout/left_menu" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_playing" >
</LinearLayout>
</LinearLayout>
</com.example.view.SlidingMenu>
</RelativeLayout>
菜单布局 left_menu.xml 简单做几个按钮当测试用的
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/jiemian"
android:orientation="vertical" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2" />
</LinearLayout>
实现方法 SlidingMenu.java
自定义ViewGroup
1.onMeasure
设置内部View以及自己的宽和高
2.onLayout
决定子View摆放的位置
*3.onTouchEvent
package com.example.view;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
public class SlidingMenu extends HorizontalScrollView {
private LinearLayout mWapper; //大布局
private ViewGroup mMenu; //菜单布局
private ViewGroup mContent; //内容布局
private int mMenuRightPadding=0; //滑出的菜单界面距离屏幕右边界的距离
private boolean once = false;
private int mScreenWidth;//屏幕宽度
private int mMenuWidth; //菜单宽度
public SlidingMenu(Context context, AttributeSet attrs) {
super(context, attrs);
//获取屏幕宽度
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
mScreenWidth = outMetrics.widthPixels;
// 将mMenuRightPadding的dp转化为px(像素值)
mMenuRightPadding = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 150, context.getResources()
.getDisplayMetrics());
}
/**
* 设置内部View以及自己的宽和高
*/
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (!once) {
mWapper = (LinearLayout) getChildAt(0); //获取Layout 即大布局
mMenu = (ViewGroup) mWapper.getChildAt(0); //获取菜单布局
mContent = (ViewGroup) mWapper.getChildAt(1); //获取内容布局
mMenuWidth = mMenu.getLayoutParams().width = mScreenWidth //设置菜单的宽度
- mMenuRightPadding;
mContent.getLayoutParams().width = mScreenWidth; //设置内容的宽度
once = true;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* 设置子View的摆放位置
* 设置偏移量 将Menu隐藏
*/
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (changed) {
//左滑的距离
this.scrollTo(mMenuWidth, 0);
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_UP:
//初始为菜单的宽度 在滑动之后变成菜单隐藏在左边的宽度
int ScrollX = getScrollX();
if (ScrollX >= mMenuWidth / 2) {
this.smoothScrollTo(mMenuWidth, 0);
}else{
this.smoothScrollTo(0, 0);
}
return true;
}
return super.onTouchEvent(ev);
}
}
MainActivity太简单就不写了
这是第一种方法,实现起来比较简单 ,但效果比较一般,并且还没加入自定义属性。
2.加入自定义属性Sliding
实现步骤:
1.在value中新建一个attr.xml
2.在布局文件中使用
3.在三个参数的构造方法中获取信息
实现目标
一.允许用户自定义菜单滑出的距离
下面是代码,根据上面三点进行操作
1.在value中新建一个attr.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="rightPadding" format="dimension"></attr>
<declare-styleable name="SlidingMenu">
<attr name="rightPadding"></attr>
</declare-styleable>
</resources>
2.修改activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:demo="http://schemas.android.com/apk/res/com.example.z14sliding"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.view.SlidingMenu
android:layout_width="match_parent"
android:layout_height="match_parent"
demo:rightPadding="150dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal" >
<include layout="@layout/left_menu" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_playing" >
</LinearLayout>
</LinearLayout>
</com.example.view.SlidingMenu>
</RelativeLayout>
3.修改SlidingMenu.java 只改变了构造函数部分
public SlidingMenu(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// 获取定义的属性
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.SlidingMenu, defStyle, 0);
int n = a.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.SlidingMenu_rightPadding:
mMenuRightPadding = a.getDimensionPixelOffset(attr,
(int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 50, context
.getResources().getDisplayMetrics()));
break;
}
}
a.recycle();
// 获取屏幕宽度
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
mScreenWidth = outMetrics.widthPixels;
}
二.添加按钮触发侧滑
1.修改SlidingMenu.class
public void openMenu() {
if (isOpen)
return;
this.smoothScrollTo(0, 0);
isOpen = true;
}
public void closeMenu() {
if (!isOpen)
return;
this.smoothScrollTo(mMenuWidth, 0);
isOpen = false;
}
public void toggle() {
if (isOpen) {
closeMenu();
} else {
openMenu();
}
}
2.MainActivity.class添加监听
package com.example.z14sliding;
import com.example.view.SlidingMenu;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.Window;
public class MainActivity extends Activity {
private SlidingMenu mleftMenu;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
mleftMenu =(SlidingMenu) findViewById(R.id.menu);
}
public void toggleMenu(View view){
mleftMenu.toggle();
}
}
至此第一种普通的侧滑讲解完了,下一步我们进阶讲一下抽屉式侧滑
3.抽屉式侧滑
初始菜单偏移量为宽度 设为300
当移动100dp时 偏移为200
当移动30pd时 偏移为270
实现:
1.修改SlidingMenu.class
/**
* 滚动发生时自动调用
*/
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
//调用属性动画
float scale=l*1.0f/mMenuWidth; //1~0变化
ViewHelper.setTranslationX(mMenu, mMenuWidth*scale);
}
4.终极目标:QQ侧滑效果
1.内容区域 1~0.7 的缩放效果
scale 1.0~0
0.7+0.3*scale
2.菜单偏移量修改
3.菜单显示时的缩放以及透明度变化
缩放:0.7~1.0
1.0-0.3*scale
透明度 0.6~1.0
0.6+0.4*(1-scale)
SlidingMenu.class
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
//调用属性动画
float scale=l*1.0f/mMenuWidth; //1~0变化
ViewHelper.setTranslationX(mMenu, mMenuWidth*scale*0.7f);
//内容区域缩放以及中心点设置
float rightScale=0.7f+0.3f*scale;
ViewHelper.setPivotX(mContent, 0);
ViewHelper.setPivotY(mContent, mContent.getHeight()/2);
ViewHelper.setScaleX(mContent, rightScale);
ViewHelper.setScaleY(mContent, rightScale);
//菜单
float leftScale=1.0f-scale*0.3f;
float leftAlpha=0.6f+0.4f*(1-scale);
ViewHelper.setScaleX(mMenu, leftScale);
ViewHelper.setScaleY(mMenu, leftScale);
ViewHelper.setAlpha(mMenu, leftAlpha);
}
好了 这就是Sliding的全部内容了,写了好久,也对Sliding有了更深的理解!!