改进Android SlidingMenu实现QQ样式边侧滑抽屉技术

改进Android SlidingMenu实现QQ样式边侧滑抽屉技术

改进Android SlidingMenu实现QQ样式边侧滑抽屉技术

我在之前写的附录文章1中介绍了Android SlidingMenu的使用,Android SlidingMenu作为第三方的边侧滑技术(也被称之为‘抽屉’),在过去的四五年中被广泛使用,但随着后来谷歌官方在Android中以官方支持的形式相继推出了DrawerLayout(附录文章2)和NavigationView(附录文章3)作为抽屉技术的标准实现后,SlidingMenu逐渐在边缘化。在以后的开发中,如果要实现抽屉的边侧滑效果,DrawerLayout和NavigationView是首选。 但是,SlidingMenu在过去毕竟盛行过,一些老旧的APP中作为继承和惯性,还在使用SlidingMenu。如果瞬间说抛弃SlidingMenu,代码切换的时间和工作量有些多。 这篇文章要写的是,如何在不改变SlidingMenu的主题结构情况下,对SlidingMenu进行代码改造和增强,实现类似QQ的边侧滑抽屉效果。 在一段时间,QQ手机客户端的边侧滑(抽屉),和SlidingMenu一样,左滑右滑切换出隐藏的菜单和功能界面,但是需要特别注意的是:QQ的边侧滑与普通的SlidingMenu边侧滑效果不同,QQ的边侧滑、当抽屉打开时候,是一种逐渐缩进缩出的放大/缩小进出效果,同时还带有一定的电影中屏幕逐渐亮/暗效果。本文将在SlidingMenu的基础上改进SlidingMenu代码,作为兼容和增强,实现QQ样式的边侧滑抽屉效果。 写一个布局文件,主布局,通常在实际的开发中,这就是要盛放主体内容的界面activity_main.xml,我简单写一个布局,主要用于测试:

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="#FF6F00" >

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerInParent="true"

android:textColor="@android:color/white"

android:textSize="80sp"

android:gravity="center"

android:text="Zhang Phil" />

MainActivity.java:

package zhangphil.slidingmenu;

import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;

import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.CanvasTransformer;

import com.nineoldandroids.view.ViewHelper;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.PorterDuff.Mode;

import android.os.Bundle;

import android.support.v4.app.Fragment;

import android.support.v4.app.FragmentActivity;

import android.support.v4.app.FragmentManager;

import android.support.v4.app.FragmentTransaction;

import android.view.Gravity;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.TextView;

public class MainActivity extends FragmentActivity {

private SlidingMenu mSlidingMenu;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mSlidingMenu = new SlidingMenu(this);

mSlidingMenu.setMode(SlidingMenu.LEFT);

mSlidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);

mSlidingMenu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT);

// 左边

mSlidingMenu.setMenu(R.layout.left_menu);

Fragment leftFragment = TestFragment.newInstance();

FragmentManager fm = getSupportFragmentManager();

FragmentTransaction ft = fm.beginTransaction();

ft.replace(R.id.left, leftFragment);

ft.commit();

// 核心关键处,这就是对SlideMenu的增强和改进。

addQQSlideStyleSlide();

}

// 为SlideMenu添加QQ样式的边侧滑

private void addQQSlideStyleSlide() {

CanvasTransformer mTransformer = new CanvasTransformer() {

@Override

public void transformCanvas(Canvas canvas, float percentOpen) {

View mainContent = mSlidingMenu.getContent();

View leftContent = mSlidingMenu.getMenu();

animateView(mainContent, leftContent, percentOpen);

}

};

// 设置滑动菜单视图的宽度

mSlidingMenu.setBehindOffsetRes(R.dimen.slidingmenu_offset);

mSlidingMenu.setFadeEnabled(false);

mSlidingMenu.setBehindCanvasTransformer(mTransformer);

}

private void animateView(View main, View left, float percent) {

float f1 = 1 - percent * 0.3f;

ViewHelper.setScaleX(main, f1);

ViewHelper.setScaleY(main, f1);

ViewHelper.setTranslationX(left, -left.getWidth() / 2.3f + left.getWidth() / 2.3f * percent);

ViewHelper.setScaleX(left, 0.5f + 0.5f * percent);

ViewHelper.setScaleY(left, 0.5f + 0.5f * percent);

ViewHelper.setAlpha(left, percent);

getWindow().getDecorView().getBackground().setColorFilter(evaluate(percent, Color.BLACK, Color.TRANSPARENT),

Mode.SRC_OVER);

}

private Integer evaluate(float fraction, Object startValue, Integer endValue) {

int startInt = (Integer) startValue;

int startA = (startInt >> 24) & 0xff;

int startR = (startInt >> 16) & 0xff;

int startG = (startInt >> 8) & 0xff;

int startB = startInt & 0xff;

int endInt = (Integer) endValue;

int endA = (endInt >> 24) & 0xff;

int endR = (endInt >> 16) & 0xff;

int endG = (endInt >> 8) & 0xff;

int endB = endInt & 0xff;

return (int) ((startA + (int) (fraction * (endA - startA))) << 24)

| (int) ((startR + (int) (fraction * (endR - startR))) << 16)

| (int) ((startG + (int) (fraction * (endG - startG))) << 8)

| (int) ((startB + (int) (fraction * (endB - startB))));

}

//

// 仅仅用于生成测试的Fragment。

// 左边侧边滑打开的抽屉

//

public static class TestFragment extends Fragment {

public static Fragment newInstance() {

Fragment fragment = new TestFragment();

return fragment;

}

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

// 仅仅显示一个TextView。

TextView tv = new TextView(getActivity());

tv.setTextColor(Color.WHITE);

tv.setText("左边");

tv.setTextSize(60.0f);

tv.setGravity(Gravity.CENTER);

return tv;

}

}

}

在自己的代码中如何使用SlideMenu本文不再详细介绍,我写的附录文章1有介绍。 如何对SlidingMenu进行改造以实现QQ样式的边侧滑抽屉技术,核心关键处就是我写在MainActivity.java里面的这部分连锁代码:

// 为SlideMenu添加QQ样式的边侧滑

private void addQQSlideStyleSlide() {

CanvasTransformer mTransformer = new CanvasTransformer() {

@Override

public void transformCanvas(Canvas canvas, float percentOpen) {

View mainContent = mSlidingMenu.getContent();

View leftContent = mSlidingMenu.getMenu();

animateView(mainContent, leftContent, percentOpen);

}

};

// 设置滑动菜单视图的宽度

mSlidingMenu.setBehindOffsetRes(R.dimen.slidingmenu_offset);

mSlidingMenu.setFadeEnabled(false);

mSlidingMenu.setBehindCanvasTransformer(mTransformer);

}

private void animateView(View main, View left, float percent) {

float f1 = 1 - percent * 0.3f;

ViewHelper.setScaleX(main, f1);

ViewHelper.setScaleY(main, f1);

ViewHelper.setTranslationX(left, -left.getWidth() / 2.3f + left.getWidth() / 2.3f * percent);

ViewHelper.setScaleX(left, 0.5f + 0.5f * percent);

ViewHelper.setScaleY(left, 0.5f + 0.5f * percent);

ViewHelper.setAlpha(left, percent);

getWindow().getDecorView().getBackground().setColorFilter(evaluate(percent, Color.BLACK, Color.TRANSPARENT),

Mode.SRC_OVER);

}

private Integer evaluate(float fraction, Object startValue, Integer endValue) {

int startInt = (Integer) startValue;

int startA = (startInt >> 24) & 0xff;

int startR = (startInt >> 16) & 0xff;

int startG = (startInt >> 8) & 0xff;

int startB = startInt & 0xff;

int endInt = (Integer) endValue;

int endA = (endInt >> 24) & 0xff;

int endR = (endInt >> 16) & 0xff;

int endG = (endInt >> 8) & 0xff;

int endB = endInt & 0xff;

return (int) ((startA + (int) (fraction * (endA - startA))) << 24)

| (int) ((startR + (int) (fraction * (endR - startR))) << 16)

| (int) ((startG + (int) (fraction * (endG - startG))) << 8)

| (int) ((startB + (int) (fraction * (endB - startB))));

}

以下这部分代码,主要是为了实现背景逐渐点亮/逐渐暗淡的效果。

getWindow().getDecorView().getBackground().setColorFilter(evaluate(percent, Color.BLACK, Color.TRANSPARENT),

Mode.SRC_OVER);

需要设置SlideMenu侧滑打开抽屉后的偏移距离,否则左边打开的窗口Menu将和普通的SlideMenu一样将完全展开铺满整个窗口,达不到QQ的那种各个窗口占据一般的效果。

Values/dimens.xml:

150dp

测试的左边侧边滑打开的抽屉后,加载的Fragment使用的布局left.xml:

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:background="#4FC3F7"

android:orientation="vertical" >

android:id="@+id/left"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:background="#F44336" >

代码写到这里,像QQ样式的边侧滑打开抽屉技术已经实现,但仍有一个细节未实现。QQ边侧滑打开抽屉时候,注意整个屏幕窗口内的背景图,好像是一个星空,要在自己的代码中也有这个背景,那么需要需要对我们自己的Activity略做修改,修改values目录下styles.xml文件主题,把要实现QQ边侧滑抽屉效果的Activity的Theme背景添加一张图片,图片需要事先放到drawable目录,我的这个例子,事先在drawable目录下放一张zhangphil_background.jpg图片:

代码运行结果(初始状态 –> 然后,从左往右的边侧滑,抽屉逐渐打开):

附录文章: 1,《集成Android SlidingMenu(SlideMenu)》链接地址:http://blog.csdn.net/zhangphil/article/details/44078805 2,《基于Android官方DrawerLayout实现抽屉导航菜单》链接地址:http://blog.csdn.net/zhangphil/article/details/48710453 3,《Android Material Design: NavigationView抽屉导航菜单》链接地址:http://blog.csdn.net/zhangphil/article/details/48931221

💡 相关推荐

女性按摩乳房的正确方法
365即时比分足球

女性按摩乳房的正确方法

📅 07-25 👀 9540
学会在WPS表格中设置单元格格式
完美365体育app下载安装

学会在WPS表格中设置单元格格式

📅 10-23 👀 4929
越愛越墮落(18+) (2017)    Full online with English subtitle for free – iQIYI