看到很多APP都用到的侧滑效果,由于自己也是自学的初学者,就在网上找了学习资料学习了一下,代码基本上都来自慕课网,在此整理记录一下,方便以后查看,也希望对别人有点帮助!
1.首先写布局文件,侧滑效果其实是在一个activity里添加了2个布局文件(我个人是这么理解的),就像是一张A4纸被横向拉伸了一样。只是我们只能看到一张A4纸张的大小!
1.1侧滑菜单的布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="vertical"
>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:layout_toRightOf="@+id/ig_01"
android:text="第一行"
android:textSize="30sp" />
<ImageView
android:id="@+id/ig_01"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="20dp"
android:src="@drawable/img_1" />
</RelativeLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:layout_toRightOf="@+id/ig_02"
android:text="第一行"
android:textSize="30sp" />
<ImageView
android:id="@+id/ig_02"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="20dp"
android:src="@drawable/img_1" />
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
效果:
1.2主布局,这里当然需要写一个继承HorizontalScrollView的自定义布局文件,
注意第一个LinearLayout的宽度是包裹内容,我自己的理解是要包含2个布局肯定不能是匹配了
RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:lly="http://schemas.android.com/apk/res/com.example.qqtest"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.SlidingMenu.SlidingMeny
android:id="@+id/id_menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/img_frame_background"
lly:rightPadding="100dp" >
<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/qq" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="toggle"
android:text="菜单" />
</LinearLayout>
</LinearLayout>
</com.example.SlidingMenu.SlidingMeny>
</RelativeLayout>
效果图:
1.3 自定义布局文件,由于也是自学,我的注释也写的很详细了
package com.example.SlidingMenu;
import com.example.qqtest.R;
import com.nineoldandroids.view.ViewHelper;
import android.content.Context;
import android.content.res.TypedArray;
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 SlidingMeny extends HorizontalScrollView {
private LinearLayout mWapper; // 布局
private ViewGroup mMenu;// 菜单布局
private ViewGroup mContent;// 主内容
private int mMenuWidth;// 菜单宽度
private int mContentWidth;// 内容宽度
private int mScreenWidth;// 屏幕宽度
private int mPaddingRight = 50;// 菜单距离右边距离
boolean once;// 只获取一次屏幕宽度的标示符
boolean isopen;// 菜单是否打开标示符(默认值是false)
/**
* 设置子view的宽和高(第一步)
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (!once) {// 确保只调用一次
mWapper = (LinearLayout) getChildAt(0);
mMenu = (ViewGroup) mWapper.getChildAt(0);
mContent = (ViewGroup) mWapper.getChildAt(1);
// menu的宽度
mMenuWidth = mMenu.getLayoutParams().width = mScreenWidth - mPaddingRight;
// content的宽度
mContentWidth = mContent.getLayoutParams().width = mScreenWidth;
once = true;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* 没有使用自定义属性的时候调用(第二步)
*
* @param context
*/
public SlidingMeny(Context context) {
this(context, null);
}
public SlidingMeny(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
/**
* 有自定义的属性时候调用(第三步),并且去values去自定义属性
*
* @param context
* @param attrs
* @param defStyleAttr
*/
public SlidingMeny(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// 获取定义属性
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.slidingM, defStyleAttr, 0);
// 获取自定义属性的数量
int n = array.getIndexCount();
// 遍历自定义属性
for (int i = 0; i < n; i++) {
int attr = array.getIndex(i);
switch (attr) {
case R.styleable.slidingM_rightPadding:
// 如果没有写值 就使用默认值50dp,此方法能是把dp转换为像素
mPaddingRight = array.getDimensionPixelSize(attr, (int) TypedValue
.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources().getDisplayMetrics()));
break;
}
}
// 用完要释放掉
array.recycle();
// 获取屏幕宽度
WindowManager wm = (WindowManager) context.getSystemService(context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
mScreenWidth = outMetrics.widthPixels;
}
/**
* 通过设置偏移量,将menu隐藏(第四步)
*
*/
@Override
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 scollX = getScrollX();// 获取X轴滑动的距离
if (scollX >= mMenuWidth / 2) {// X轴距离大于左侧菜单宽度的二分之一就滑动界面
this.smoothScrollTo(mMenuWidth, 0);// 滑动的距离和动画
isopen = false;// 并将菜单表示符号置为false
} else {
this.smoothScrollTo(0, 0);// 小于二分之一就不滑动界面,返回到原来的
isopen = true;
}
return true;
}
return super.onTouchEvent(ev);
}
/**
* 抽屉式效果(第六步)
*/
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
float scall = l * 1.0f / mMenuWidth;// 缩放比例(可以自己写出自己想要的效果)
float rightScale = (float) (0.7 + 0.3 * scall);// 右侧缩放
float leftScale = (float) (1.0 - 0.3 * scall);// 左侧缩放
float leftAlpha = (float) (1 - 0.4 * scall);// 透明度
// menu的缩放点以及缩放动画 此时要导入第三方的包,兼容3.0一下。nineoldandroids-2.4.0.jar
ViewHelper.setPivotX(mMenu, leftScale);// 设置缩放点
ViewHelper.setPivotY(mMenu, leftScale);
ViewHelper.setTranslationX(mMenu, mMenuWidth * scall * 0.7f);// 设置缩放动画
ViewHelper.setAlpha(mMenu, leftAlpha);
// content 设置缩放的中心点在左边框的中心以及缩放的比例
ViewHelper.setPivotX(mContent, 0);
ViewHelper.setPivotY(mContent, mContent.getHeight() / 2);
ViewHelper.setScaleX(mContent, rightScale);
ViewHelper.setScaleY(mContent, rightScale);
}
/**
* 打开菜单
*/
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();
}
}
}
1.4 最后在MainActivity里调用,这里只需要注意此处要在主activity里面的自定义布局添加id
package com.example.qqtest;
import com.example.SlidingMenu.SlidingMeny;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
public class MainActivity extends Activity {
private SlidingMeny meny;// 获取自定义布局的ID
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
meny = (SlidingMeny) findViewById(R.id.id_menu);
}
public void toggle(View view) {
meny.toggle();// 调用开关
}
}
这个包百度一下就可以找到!
nineoldandroids-2.4.0.jar
1.4自定义属性,在values里新建
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="slidingM">
<attr name="rightPadding" format="dimension"></attr>
</declare-styleable>
</resources>