Android实现仿QQ5.0的侧滑效果

本文详细介绍了如何实现QQ5.0侧滑效果,并提供了完整的示例代码,包括自定义View、事件处理、单位换算等关键知识点,以及如何在Android中实现菜单侧滑功能。通过实例学习,您可以轻松掌握侧滑效果的开发技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        前段时间准备学习下侧滑效果的实现,不经意间发现了穆课网有个介绍QQ5.0侧滑的视频,于是学习了下,稍作整理,留作自用。

        首先看一下效果,第一张就是截的QQ的图模拟内容界面,第二张为向左侧滑时的效果。



一、整体实现思路

        两个界面本质是一个View,左右排列,通过一个水平滚动条来实现(示例中自定义了一个View继承自HorizontalScrollView)。起始状态滚动条在靠近中间的位置,这样就显示出了内容区域。当从内容区向左侧滑时,滑到一定的范围就直接将滚动条设置到最左边,这样就看到了左边的菜单。向右侧滑也是类似。为了达到在菜单边界露出内容区域的效果,需要设置菜单的宽度比屏幕宽度小一些(小的宽度就是露出内容区域的宽度)。需要的知识点如下:1. 自定义View的onMeasure事件与onLayout事件;2. onTouchEvent事件;3.获取屏幕的宽度和高度;4. 获取和设置滚动条的偏移量并实现切换的动画;5.单位换算;6.设置不显示标题。

二、例子所需的知识储备

        1. 自定义View的onMeasure事件与onLayout事件;
        首先View的onMeasure事件可以设置View中子控件的大小,onLayout事件可设置子控件在该View中的位置。 在这个例子中在onMeasure事件中设置左边菜单的宽度和右边内容区域的宽度,然后在onLayout事件中确定初始显示内容区域(设置滚动条的位置)。
        2. onTouchEvent事件
        这个响应用户的滑动事件,当用户手指抬起的时候要判断水平滑动的距离,当达到一定的范围就切换界面(也就是设置滚动条的位置)。
        3.获取屏幕的宽度和高度
WindowManager wm = (WindowManager) context
		.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
mScreenWidth = outMetrics.widthPixels;
        4. 获取和设置滚动条的偏移量并实现切换的动画
        设置滚动条的位置采用scrollTo,该方法是不带动画,而smoothScrollTo是带动画的,能让人看到滑过去的效果,而不是直接切换。
        示例中this.smoothScrollTo(mMenuWidth, 0);表示将滚动条移动到mMenuWidth宽度处。
        5.单位换算
        TypedValue.applyDimension方法,示例如下:
// 把DP转换成px
mMenuRightPadding = (int) TypedValue.applyDimension(
		TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources()
		.getDisplayMetrics());
        6.设置不显示标题
        在AndroidManifest.xml设置主题android:theme="@android:style/Theme.NoTitleBar"。

三、完整示例代码:

        activity_main.xml代码:

<?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"
    android:background="@drawable/left_menu" >
    <com.example.qq1024.SlidingMenu
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="none" >
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:orientation="horizontal" >
            <include layout="@layout/left_menulayout" />
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@drawable/qq_main" >
            </LinearLayout>
        </LinearLayout>
    </com.example.qq1024.SlidingMenu>
</RelativeLayout>

        left_menulayout.xml代码:

<?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"
    android:background="@drawable/left_menu" >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:orientation="vertical" >
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
            <ImageView
                android:id="@+id/first_img"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                android:layout_marginTop="20dp"
                android:src="@drawable/first_menu" />
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                android:layout_toRightOf="@id/first_img"
                android:text="第一个菜单"
                android:textColor="#FFF"
                android:textSize="20sp" />
        </RelativeLayout>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
            <ImageView
                android:id="@+id/second_img"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                android:layout_marginTop="20dp"
                android:src="@drawable/second_menu" />
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                android:layout_toRightOf="@id/second_img"
                android:text="第二个菜单"
                android:textColor="#FFF"
                android:textSize="20sp" />
        </RelativeLayout>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
            <ImageView
                android:id="@+id/third_img"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                android:layout_marginTop="20dp"
                android:src="@drawable/third_menu" />
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                android:layout_toRightOf="@id/third_img"
                android:text="第三个菜单"
                android:textColor="#FFF"
                android:textSize="20sp" />
        </RelativeLayout>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
            <ImageView
                android:id="@+id/forth_img"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                android:layout_marginTop="20dp"
                android:src="@drawable/forth_menu" />
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                android:layout_toRightOf="@id/forth_img"
                android:text="第四个菜单"
                android:textColor="#FFF"
                android:textSize="20sp" />
        </RelativeLayout>
    </LinearLayout>
</RelativeLayout>

        SlidingMenu.java代码:

package com.example.qq1024;

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.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 mScreenWidth;
	private int mMenuRightPadding = 50;
	private boolean once = false;
	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;
		// 把DP转换成px
		mMenuRightPadding = (int) TypedValue.applyDimension(
				TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources()
						.getDisplayMetrics());
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		if (!once) {
			mWapper = (LinearLayout) getChildAt(0);
			mMenu = (ViewGroup) mWapper.getChildAt(0);
			mContent = (ViewGroup) mWapper.getChildAt(1);
			mMenu.getLayoutParams().width = mScreenWidth - mMenuRightPadding;
			mContent.getLayoutParams().width = mScreenWidth;
			mMenuWidth = mMenu.getLayoutParams().width;
			once = true;
		}
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}

	@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 scrollx = getScrollX();
			if (scrollx >= mMenuWidth / 2) {
				this.smoothScrollTo(mMenuWidth, 0);
			} else {
				this.smoothScrollTo(0, 0);
			}
			return true;

		default:
			break;
		}
		return super.onTouchEvent(ev);
	}
}

        MainActivity.java代码:

package com.example.qq1024;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}
}

        最后还是要感谢穆课网上的hyman的视频,代码内容几乎跟视频中的一样,只是做了点事件的调查和界面的修饰,然后以文字显示,方便以后使用。

        源码下载

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值