继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Android之高仿QQ6.6.0侧滑效果(背景动画、透明+沉浸式状态栏、渐变效果)

天罡北斗阵
关注TA
已关注
手记 1
粉丝 2
获赞 27

根据需求实现类似QQ侧滑效果,之前看到过很多实现方式通过SlidingMenu,但是既然官方推出了自己的专属控件,那么使用DrawerLayout就是不二选择。且看下文。

一、先来看看官方文档解释

DrawerLayout充当窗口内容的顶层容器,允许交互式“抽屉”的观点,以从窗口的边缘拉出。抽屉的定位和布局是使用控制机器人:layout_gravity 属性对应到您想要的抽屉,从出现的观点哪边儿的观点:左或右。(或者在启动支持布局方向平台版本/结束)。要使用DrawerLayout,定位你的主要内容视图的第一个孩子,宽度和高度match_parent。添加抽屉为孩子意见的主要内容视图后,设置layout_gravity适当。抽屉通常使用match_parent的高度与宽度固定。DrawerLayout.DrawerListener可以用来监测抽屉意见的状态和运动。避免进行昂贵的操作,如动画,因为它可能会导致口吃过程中的布局; 尝试在执行昂贵的操作STATE_IDLE状态。DrawerLayout.SimpleDrawerListener提供每个回调方法的默认/无操作实现。

二、再来看看继承关系 这里写图片描述
三、效果图(真实图和效果图)QQ6.6版本侧滑截图
说明: 此图来自网络。
实现的效果截图
说明: 此图是实现的效果截图,在模拟器上运行的,建议换作真机看效果,状态栏的渐变更明显。
模拟器运行gif效果图
说明: 此图是模拟器运行的完整效果图,建议使用真机看效果。涉及的知识点:状态栏的设置,渐变效果;属性动画;TabLayout使用;最主要的DrawerLayout的使用。

下面就来看代码片段

主页面的布局

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/id_drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        android:orientation="vertical">

        <RelativeLayout
            android:id="@+id/rl_main_top"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:background="#14B6F6"
            android:gravity="center_vertical">

            <ImageView
                android:id="@+id/iv_navigation_icon"
                android:layout_width="35dp"
                android:layout_height="35dp"
                android:layout_marginLeft="10dp"
                android:src="@drawable/ic_launcher" />

            <TextView
                android:id="@+id/tv_center"
                android:layout_width="wrap_content"
                android:layout_height="35dp"
                android:layout_centerHorizontal="true"
                android:gravity="center"
                android:text="消息    电话"
                android:textColor="#ffffff"
                android:textSize="15sp" />

            <TextView
                android:id="@+id/tv_right"
                android:layout_width="35dp"
                android:layout_height="35dp"
                android:layout_alignParentRight="true"
                android:layout_marginRight="8dp"
                android:gravity="center"
                android:textColor="#ffffff"
                android:textSize="15sp" />
        </RelativeLayout>

        <android.support.design.widget.TabLayout
            android:id="@+id/tab_main_bottom"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            app:tabGravity="center"
            app:tabIndicatorHeight="0dp"
            app:tabSelectedTextColor="@color/colorPrimary">
            <android.support.design.widget.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:icon="@drawable/skin_tab_icon_conversation_selected" />
            <android.support.design.widget.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:icon="@drawable/skin_tab_icon_contact_selected" />
            <android.support.design.widget.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:icon="@drawable/skin_tab_icon_plugin_selected" />
        </android.support.design.widget.TabLayout>
        <android.support.v4.view.ViewPager
            android:id="@+id/vp_main_contents"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_above="@id/tab_main_bottom"
            android:layout_below="@id/rl_main_top">

        </android.support.v4.view.ViewPager>
    </RelativeLayout>

    <include layout="@layout/draw_menu_layout" />

</android.support.v4.widget.DrawerLayout>

说明: 在这里可以看到,最外层布局是DrawerLayout,里面嵌套了两层布局,一层是RelativeLayout,一层是include进来的draw_menu_layout,这里需要说明一下,drawerlayout的子布局第一层是主页面的内容,第二层是侧滑的内容,所以才有上面的布局。当然也可以有第三层布局,作为第二层的子布局使用。

左侧布局内容

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="280dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:clickable="true"
    android:tag="left">

    <ImageView
        android:id="@+id/iv_drawer_bg"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/fnn" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <RelativeLayout
            android:id="@+id/id_draw_menu_header"
            android:layout_width="match_parent"
            android:layout_height="200dp">

            <TextView
                android:id="@+id/id_draw_menu_item_backup"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="20dp"
                android:layout_marginTop="100dp"
                android:drawableLeft="@drawable/ic_launcher"
                android:drawablePadding="15dp"
                android:gravity="center"
                android:text="code小生"
                android:textColor="@android:color/white"
                android:textSize="15sp" />

            <ImageView
                android:id="@+id/id_draw_menu_item_download"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_alignParentRight="true"
                android:layout_marginRight="15dp"
                android:layout_marginTop="35dp"
                android:scaleType="centerCrop"
                android:src="@drawable/qrcode_min_cm" />
        </RelativeLayout>

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/white">

            <TextView
                android:id="@+id/id_draw_menu_item_main_tv"
                android:layout_width="match_parent"
                android:layout_height="40dp"
                android:layout_alignParentBottom="true"
                android:gravity="center_vertical"
                android:paddingLeft="15dp"
                android:text="设置"
                android:textSize="18sp" />

            <ListView
                android:id="@+id/id_draw_menu_item_list_select"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_alignParentTop="true"
                android:layout_above="@id/id_draw_menu_item_main_tv"
                android:divider="@android:color/transparent"
                android:overScrollMode="never"
                android:scrollbars="none" />
        </RelativeLayout>
    </LinearLayout>
</FrameLayout>

说明: 这里就是一个不同的布局了,和平时写法没啥区别。需要注意的是使用FrameLayout的原因。

下面就来看看我们的主页代码:

package com.example.mjj.drawerlayoutqq;

import android.animation.ObjectAnimator;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

/**
 * 仿QQ6.6.0版本侧滑效果
 * <p>
 * DrawerLayout内容偏移,背景动画,主页面导航图标渐变,状态栏渐变色.
 * <p>
 * Created by Mjj on 2016/12/7.
 */
public class MainActivity extends AppCompatActivity {

    private SystemBarTintManager tintManager;
    private DrawerLayout mDrawerLayout;
    private ImageView ivNavigation;

    private ImageView ivDrawerBg; // 侧边有动画效果的背景图片

    private TextView tvCenter, tvRight;

    private int[] tabIcons = {R.drawable.ngq, R.drawable.nti, R.drawable.nbb};
    private TabLayout tabLayout;
    private ViewPager viewPager;

    private ListView listView;
    private String strings[] = {"开通会员", "QQ钱包", "个性装扮", "我的收藏", "我的相册", "我的文件", "我的日程", "我的名片夹"};

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            setTranslucentStatus(true);
            tintManager = new SystemBarTintManager(this);
            tintManager.setStatusBarTintEnabled(true);
            tintManager.setStatusBarTintColor(Color.parseColor("#14B6F6"));
        }
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        ivNavigation = (ImageView) findViewById(R.id.iv_navigation_icon);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.id_drawer_layout);

        // 设置侧滑背景图片的动画
        ivDrawerBg = (ImageView) findViewById(R.id.iv_drawer_bg);
        float curTranslationY = ivDrawerBg.getTranslationY();
        ObjectAnimator animator = ObjectAnimator.ofFloat(ivDrawerBg, "translationY", curTranslationY,
                -70f, 60, curTranslationY);
        animator.setDuration(5000);
        animator.setRepeatCount(ObjectAnimator.INFINITE);
        animator.start();

        tvCenter = (TextView) findViewById(R.id.tv_center);
        tvRight = (TextView) findViewById(R.id.tv_right);

        tabLayout = (TabLayout) findViewById(R.id.tab_main_bottom);
        viewPager = (ViewPager) findViewById(R.id.vp_main_contents);

        // 同时添加图标和文字需要自定义view,此种方式无效,和适配器关联的时候,就被隐藏掉了.
//        tabLayout.addTab(tabLayout.newTab().setIcon(tabIcons[0]));
//        tabLayout.addTab(tabLayout.newTab().setIcon(tabIcons[1]));
//        tabLayout.addTab(tabLayout.newTab().setIcon(tabIcons[2]));

        MyFragmentPagerAdapter adapter = new MyFragmentPagerAdapter(getSupportFragmentManager(),
                tabIcons, this);
        viewPager.setAdapter(adapter);
        tabLayout.setupWithViewPager(viewPager);

        //设置监听
        ivNavigation.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                toggle();
            }
        });

        listView = (ListView) mDrawerLayout.findViewById(R.id.id_draw_menu_item_list_select);
        listView.setAdapter(new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, strings));
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                Toast.makeText(MainActivity.this, strings[i], Toast.LENGTH_SHORT).show();
            }
        });

        mDrawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {

            /**
             * @param drawerView
             * @param slideOffset   偏移(0-1)
             */
            @Override
            public void onDrawerSlide(View drawerView, float slideOffset) {
                // 导航图标渐变效果
                ivNavigation.setAlpha(1 - slideOffset);
                // 判断是否左菜单并设置移动(如果不这样设置,则主页面的内容不会向右移动)
                if (drawerView.getTag().equals("left")) {
                    View content = mDrawerLayout.getChildAt(0);
                    int offset = (int) (drawerView.getWidth() * slideOffset);
                    content.setTranslationX(offset);

                    // 缩放效果(之前QQ效果)
//                    content.setTranslationX(1 - slideOffset * 0.5f);
//                    content.setTranslationY(1 - slideOffset * 0.5f);
                }
                tintManager.setStatusBarAlpha(1 - slideOffset);
            }

            @Override
            public void onDrawerOpened(View drawerView) {
            }

            @Override
            public void onDrawerClosed(View drawerView) {
            }

            /**
             * 当抽屉滑动状态改变的时候被调用
             * 状态值是STATE_IDLE(闲置-0),STATE_DRAGGING(拖拽-1),STATE_SETTLING(固定-2)中之一。
             * 抽屉打开的时候,点击抽屉,drawer的状态就会变成STATE_DRAGGING,然后变成STATE_IDLE.
             *
             * @param newState
             */
            @Override
            public void onDrawerStateChanged(int newState) {

            }
        });
    }

    // 设置状态栏透明状态
    private void setTranslucentStatus(boolean on) {
        Window win = getWindow();
        WindowManager.LayoutParams winParams = win.getAttributes();
        final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
        if (on) {
            winParams.flags |= bits;
        } else {
            winParams.flags &= ~bits;
        }
        win.setAttributes(winParams);
    }

    /**
     * 自定义NavigationIcon设置关联DrawerLayout
     */
    private void toggle() {
        int drawerLockMode = mDrawerLayout.getDrawerLockMode(GravityCompat.START);
        if (mDrawerLayout.isDrawerVisible(GravityCompat.START)
                && (drawerLockMode != DrawerLayout.LOCK_MODE_LOCKED_OPEN)) {
            mDrawerLayout.closeDrawer(GravityCompat.START);
        } else if (drawerLockMode != DrawerLayout.LOCK_MODE_LOCKED_CLOSED) {
            mDrawerLayout.openDrawer(GravityCompat.START);
        }
    }
}

说明: 就是最核心的代码了,关于每个部分的功能都有注释,就不多说了。完整代码已上传至github,微信关注“code小生”查看链接地址。

建议:关于TabLayout使用不是很清楚的可以看看《TabLayout两种添加tab方式,结合ViewPager+Fragment实现常见界面视图》、《Android App之底部tab导航常用实现方案总结》关于本文想更近一步阅读,请看《Android之高仿QQ6.6.0侧滑效果(背景动画、透明+沉浸式状态栏、渐变效果

打开App,阅读手记
6人推荐
发表评论
随时随地看视频慕课网APP