仿QQ6.0主页侧滑效果的实现,我们使用众所周知的我们常用的HorizontalScrollView来实现QQ的侧滑效果。首先我们来看一下运行效果图:
首先我们来打造一个侧滑菜单的menu类,让其继承自HorizontalScrollView。具体的实现我们来一起看代码SlidingMenu.java
源码下载我稍后在评论中给出,等了好久csdn不出地址没办法。。。
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import com.xyliwp.dayday.R;
/**
* 侧滑菜单
* Created by wenpengli on 2017/1/17.
*/
public class SlidingMenu extends HorizontalScrollView{
private Context context;
//菜单的内容
private View mMenuView;
private ViewGroup mContentView;
//菜单的宽度
private int mMenuWidth;
//手势处理类 主要用来处理手势快速华东
private GestureDetector mGestureDetector;
//判断菜单是否打开
private boolean mMenuIsOpen = false;
private ImageView mShadowIV;
public SlidingMenu(Context context) {
this(context,null);
}
public SlidingMenu(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public SlidingMenu(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SlidingMenu);
float rightPadding = typedArray.getDimension(R.styleable.SlidingMenu_rightPadding,dip2px(50));
//计算菜单的宽度 = 屏幕的宽度-自定义右边留出的宽度
mMenuWidth = (int)(getScreenWidth() - rightPadding);
typedArray.recycle();
//实例化手势处理类
mGestureDetector = new GestureDetector(context,new GestrueListener());
this.context = context;
}
/**
* 把dip转化为像素
* @param dip
* @return
*/
private float dip2px(int dip){
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,dip,getResources().getDisplayMetrics()
);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
//获取根View也就是外层的LinearLayout
ViewGroup container = (ViewGroup)this.getChildAt(0);
int containerChaildcount = container.getChildCount();
if (containerChaildcount > 2){
//里面至于讯仿两个布局 一个是menu菜单 一个是content的内容
throw new IllegalStateException("我们规定只允许仿两个VIew");
}
//获取菜单和内容的布局
mMenuView = container.getChildAt(0);
//给内容添加阴影效果
mContentView = new FrameLayout(context);
ViewGroup.LayoutParams contentParams = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
);
// 4.2.2.获取菜单和内容布局
mMenuView = container.getChildAt(0);
// 7.给内容添加阴影效果
// 7.1 先new一个主内容布局用来放 阴影和LinearLayout原来的内容布局
mContentView = new FrameLayout(context);
contentParams = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
// 7.2 获取原来的内容布局,并把原来的内容布局从LinearLayout中异常
View oldContentView = container.getChildAt(1);
container.removeView(oldContentView);
// 7.3 把原来的内容View 和 阴影加到我们新创建的内容布局中
mContentView.addView(oldContentView);
// 7.3.1 创建阴影ImageView
mShadowIV = new ImageView(context);
mShadowIV.setBackgroundColor(Color.parseColor("#00000000"));
mContentView.addView(mShadowIV);
// 7.4 把包含阴影的新的内容View 添加到 LinearLayout中
container.addView(mContentView);
// 4.2.3.指定内容和菜单布局的宽度
// 4.2.3.1 菜单的宽度 = 屏幕的宽度 - 自定义的右边留出的宽度
mMenuView.getLayoutParams().width = mMenuWidth;
// 4.2.3.2 内容的宽度 = 屏幕的宽度
mContentView.getLayoutParams().width = getScreenWidth();
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
//处理手指快速华东
if (mGestureDetector.onTouchEvent(ev)){
return mGestureDetector.onTouchEvent(ev);
}
switch (ev.getAction()){
case MotionEvent.ACTION_UP:
//手指抬起来获取滚动的位置
int currentScrollx = getScrollX();
if (currentScrollx > mMenuWidth/2){
//关闭菜单
closeMenu();
}else {
//打开菜单
openMenu();
}
return false;
}
return super.onTouchEvent(ev);
}
/**
* 打开菜单
*/
private void openMenu(){
smoothScrollTo(0,0);
mMenuIsOpen = true;
}
/**
* 关闭菜单
*/
private void closeMenu(){
smoothScrollTo(mMenuWidth,0);
mMenuIsOpen = false;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
//布局制定后 会从新拜访的子布局,当其摆放完毕后 让菜单滚动到不可见状态
if (changed){
scrollTo(mMenuWidth,0);
}
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
//实现左边抽屉式动画效果
mMenuView.setTranslationX(1*0.8f);
float gradientValue = 1*1f / mMenuWidth;
float shadowAlpha = 1-gradientValue;
mShadowIV.setAlpha(shadowAlpha);
}
private class GestrueListener extends GestureDetector.SimpleOnGestureListener{
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
//房手指快速华东式 毁掉方法
//如果菜单打开 并且是向左快速华东的 切换到菜单状态
if (mMenuIsOpen){
if (velocityX < -500){
toggleMenu();
return true;
}
}else {
//如果是向右则 且菜菜单关闭切换回菜单状态\
if (velocityY > 500){
toggleMenu();
return true;
}
}
return false;
}
}
/**
* 切换菜单状态
*/
public void toggleMenu(){
if (mMenuIsOpen){
closeMenu();
}else {
openMenu();
}
}
/**
* 获取屏幕的宽度
* @return
*/
public int getScreenWidth(){
Resources resources = this.getResources();
DisplayMetrics dm = resources.getDisplayMetrics();
return dm.widthPixels;
}
}
在上代码中我们提到了styleable资源,如果不清楚styleable文件在哪设置,那么我们来简单的介绍一下styleable,它一般存放我们自定义控件的一些属性,该文件在values包下建立attrs.xml,在该xml下我们进行styleable的属性设置,xml的代码如下
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="SlidingMenu">
<attr name="rightPadding" format="dimension"/>
</declare-styleable>
</resources>
接下来就是主Activity的加载:
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.xyliwp.dayday.R;
/**
* Created by wenpengli on 2017/1/17.
*/
public class SlidAcivity extends Activity{
private SlidingMenu slidingMenu;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_slidingmenu);
slidingMenu = (SlidingMenu)findViewById(R.id.slidingMenuActivity);
Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
slidingMenu.toggleMenu();
Toast.makeText(SlidAcivity.this,"菜单切换",Toast.LENGTH_SHORT).show();
}
});
}
}
对于XML的代码分别如下:主XML
<?xml version="1.0" encoding="utf-8"?>
<com.xyliwp.dayday.sideslipmenu.SlidingMenu
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="@+id/slidingMenuActivity"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:rightPadding="62dp"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<include layout="@layout/layout_slid_menu"></include>
<include layout="@layout/layout_slid_content"></include>
</LinearLayout>
</com.xyliwp.dayday.sideslipmenu.SlidingMenu>
菜单XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/bg2" />
</LinearLayout>
主页面的内容XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/bt1">
<Button
android:layout_width="60dp"
android:layout_height="60dp"
android:id="@+id/button"
android:text=""
android:background="#00000000"/>
</LinearLayout>
就这样我们完成了很简单的仿QQ6.0的侧滑效果,然后你们可以发挥想象完成你们想完成的APP。