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

简介: 改进Android SlidingMenu实现QQ样式边侧滑抽屉技术我在之前写的附录文章1中介绍了Android SlidingMenu的使用,Android SlidingMenu作为第三方的边侧滑技术(也被称之为‘抽屉’),在过去的四五年中被广泛使用,但随着后来谷歌官方在Android中以官方支持的形式相继推出了DrawerLayout(附录文章2)和NavigationView(附录文章3)作为抽屉技术的标准实现后,SlidingMenu逐渐在边缘化。

改进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,我简单写一个布局,主要用于测试:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"
    android:background="#FF6F00" >  
      
    <TextView  
        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" />  
  
</RelativeLayout>


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:

<dimen name="slidingmenu_offset">150dp</dimen>


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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="#4FC3F7"
    android:orientation="vertical" >

    <FrameLayout
        android:id="@+id/left"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#F44336" >
    </FrameLayout>

</LinearLayout>


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

<resources>

    <!--
        Base application theme, dependent on API level. This theme is replaced
        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
    -->
    <style name="AppBaseTheme" parent="android:Theme.Light">
        <!--
            Theme customizations available in newer API levels can go in
            res/values-vXX/styles.xml, while customizations related to
            backward-compatibility can go here.
        -->
    </style>

    <!-- Application theme. -->
    <style name="AppTheme" parent="AppBaseTheme">
        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
    
    	<!-- zhang phil增加的背景,作为QQ样式边侧滑打开抽屉时候整个窗体背景图-->
    	<item name="android:windowBackground">@drawable/zhangphil_background</item>
    </style>

</resources>



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



附录文章:
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

相关文章
|
7月前
|
存储 消息中间件 人工智能
【05】AI辅助编程完整的安卓二次商业实战-消息页面媒体对象(Media Object)布局实战调整-按钮样式调整实践-优雅草伊凡
【05】AI辅助编程完整的安卓二次商业实战-消息页面媒体对象(Media Object)布局实战调整-按钮样式调整实践-优雅草伊凡
226 11
【05】AI辅助编程完整的安卓二次商业实战-消息页面媒体对象(Media Object)布局实战调整-按钮样式调整实践-优雅草伊凡
|
JavaScript 前端开发 Android开发
【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
491 13
【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
|
11月前
|
搜索推荐 Android开发 开发者
Android星级评分条RatingBar样式的改变及出现问题的解决方法
本文介绍了自定义 RatingBar 的实现方法,通过布局文件、layer-list 样式文件和 style 文件的配置完成个性化星星评分效果。关键步骤包括:1) 在布局文件中添加 RatingBar 并引用样式;2) 创建 layer-list 文件定义背景、次级进度和进度图片;3) 在 style 文件中定义 RatingBar 样式并应用到布局中。可能出现的问题及解决办法:直接报错通常是图片素材过大,调整尺寸即可;星星流眼泪是图片形状问题,需将图片置于透明圆形或正方形内重新组合。附有具体代码示例,方便开发者快速上手实现自定义评分组件。
446 12
|
11月前
|
Android开发 开发者
Android中Dialog位置+样式的设置
本文介绍了在Android开发中如何设置Dialog的位置和样式。通过自定义`MyDialog`类,可以灵活调整Dialog的显示位置,例如将其固定在屏幕底部,并设置宽度匹配父布局。同时,文章还展示了如何模仿Android原生Dialog样式,通过定义`MyDialogStyle`去除标题栏、设置背景透明度、添加阴影效果以及配置点击外部关闭等功能,从而实现更加美观和符合需求的Dialog效果。代码示例详细,便于开发者快速上手实现。
588 2
|
11月前
|
XML 搜索推荐 Android开发
Android改变进度条控件progressbar的样式(根据源码修改)
本文介绍了如何基于Android源码自定义ProgressBar样式。首先分析了系统源码中ProgressBar样式的定义,发现其依赖一张旋转图片实现动画效果。接着分两步指导开发者实现自定义:1) 模仿源码创建一个旋转动画XML文件(放置在drawable文件夹),修改图片为自定义样式;2) 在UI控件中通过`indeterminateDrawable`属性应用该动画。最终实现简单且个性化的ProgressBar效果,附带效果图展示。
636 2
|
11月前
|
Android开发
Android控件样式的抽取(小提及快捷方式)
在Android开发中,若多个控件样式重复,可抽取公共部分以简化代码。例如对EditText提取样式,通过编辑`styles.xml`实现复用。为提高效率,Android Studio提供自动提取Style功能:右键点击控件样式选项,选择“Style...”,勾选需要提取的属性后确认,即可快速生成样式代码,显著提升开发便利性。
315 2
|
存储 编解码 开发工具
Android平台毫秒级低延迟HTTP-FLV直播播放器技术探究与实现
本文详细探讨了在Android平台上实现HTTP-FLV播放器的过程。首先介绍了FLV格式的基础,包括文件头和标签结构。接着分析了HTTP-FLV传输原理,通过分块传输实现流畅播放。然后重点讲解了播放器的实现步骤,涵盖网络请求、数据解析、音视频解码与渲染,以及播放控制功能的设计。文章还讨论了性能优化和网络异常处理的方法,并总结了HTTP-FLV播放器的技术价值,尤其是在特定场景下的应用意义。
687 11
|
JavaScript 搜索推荐 Android开发
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
539 8
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
|
数据采集 JavaScript Android开发
【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
594 7
【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
|
安全 Android开发 iOS开发
escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
escrcpy 是一款基于 Scrcpy 的开源项目,使用 Electron 构建,提供图形化界面来显示和控制 Android 设备。它支持 USB 和 Wi-Fi 连接,帧率可达 30-120fps,延迟低至 35-70ms,启动迅速且画质清晰。escrcpy 拥有丰富的功能,包括自动化任务、多设备管理、反向网络共享、批量操作等,无需注册账号或广告干扰。适用于游戏直播、办公协作和教育演示等多种场景,是一款轻量级、高性能的 Android 控制工具。
1277 1

热门文章

最新文章