• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > Android 高仿华为手机Tab页滑动导航效果

Android 高仿华为手机Tab页滑动导航效果

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了华为手机有高仿的吗,华为mate1高仿机,高仿华为,高仿华为p9,高仿华为手机等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

Android 高仿华为手机Tab页滑动导航效果


首先带大家看一下实现效果,用了两种实现方式:
1.基于LinearLayout实现,导航栏不可响应手指滑动
2.基于HorizontalScrollView实现,导航栏可响应手指滑动

实现方式虽然不一样,但是使用的是一样的,因为我接口封装的一模一样,下面看实现效果。
基于LinearLayout的实现:
基于LinearLayout实现的滑动导航

基于HorizontalScrollView的实现:
基于HorizontalScrollView实现的滑动导航

两者效果一样,区别就在于导航条可否随用户操作滑动。

下面只说明LinearLayout实现,HorizontalScrollView仅仅是套了一层LinearLayout,因为它只允许套一个子控件。

需求开发点:
1.自定义控件的编写(通用方法:构造函数、init()、onMeasure、onLayout、onDraw、dispatchDraw)
2.白色圆点的偏移量的计算
3.当Tab页超过5个的时候,白点和LinearLayout内容的组合滑动,达到白点不动,而文字移动的效果。

实现这三点,这个控件就算完事,当然一些细节方面的,可以根据自己的需求去调优。

1.自定义控件的编写
1) 这里主要是onMeasure方法的复写,不能用默认的onMeasure,需要我们根据Tab的数量去计算,下图是1-6个Tab的measure结果
这里写图片描述
这个就是根据Tab的数量平分屏幕的宽,当数量超过5个的时候,为了保持效果,只显示5个,超出的内容将其追加到屏幕外面,屏幕是有界的,视图是无界的,你可以无限往右边添加,只要内存能容下,可以用个for循环无限添加看看发生什么。

2) 复写dispatchDraw方法,这里dispatchDraw方法的作用就是画一个白色的圆点。

白色圆点的偏移量的计算
这个得靠ViewPager的OnPageChangeListener,通过它onPageScrolled的回调去计算,计算好了调用invalidate()去重绘。

当Tab页超过5个的时候,白点和LinearLayout内容的组合滑动,达到白点不动,而文字移动的效果。
当滑动到第5个Tab,如果只是白色圆点移动就会移动到屏幕外面去,这个时候也需要让LinearLayout内容联动,通过scrollTo方法,往与白点相反的方向移动内容,使其和白点的移动达到平衡,这样白点不动,上面的标题内容移动。

下面分析,写该控件需要的一些变量,先看截图:
这里写图片描述

1.需要白点是吧,我们用画笔画,所以Paint需要
2.白点画多大?所以需要一个白点的半径变量radius
3.白点的偏移量,我们定义一个变量mOffset,根据ViewPager的滑动动态计算
4.上面还有一排文字,用TextView实现,这个TextView是根据Tab的数量动态添加的,数量不可控,我这里并没有定义成变量。但是文字内容对应的是一个Fragment的标题,也就是说标题和Fragment是一一对应的关系。OK用Map。

    /**
     * 存放Tab的集合 Key:导航栏的标题 Fragment:导航页
     */
    private Map mTabs;

TextView就是根据mTabs的数量动态添加的。
5.我们怎么去计算滑动偏移量呢?这个得靠ViewPager的OnPageChangeListener,通过它onPageScrolled的回调去计算mOffset,就是通过这种计算圆点的偏移,这里我持有了一个ViewPager的引用,所以有变量mViewPager,其实要不要关系不大.
6.屏幕最大可显示的Tab数量MAX_VISIBLE_TAB_COUNTS,总不能有100个你就显示100个吧.
7.实际屏幕上可显示的Tab数量mRealVisibleTabCounts
8.屏幕宽度mScreenWidth辅助onMeasure计算的

下面是实现代码:

package com.csm.hwtab;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Cap;
import android.graphics.Paint.Style;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
 * @author Rander.C
 */
@SuppressLint("NewApi")
public class TabLinearLayout extends LinearLayout implements OnClickListener, OnPageChangeListener {
    /**
     * 最大可显示的Tab数,可写成自定义属性在xml里面配置
     */
    private static final int MAX_VISIBLE_TAB_COUNTS = 5;
    /**
     * 实际可见的Tab数,比如有8个Tab,超过8个,为了保证效果,最多显示5个
     * 此时mRealVisibleTabCounts为5
     * 如果只有3个tab小于5个,则mRealVisibleTabCounts为3
     * 并根据这个去计算每个tab的宽度,屏幕宽度除以mRealVisibleTabCounts嘛
     */
    private int mRealVisibleTabCounts;
    /**
     * 小圆点滑动偏移量
     */
    private float mOffset;

    /**
     * 绘制小圆点画笔
     */
    private Paint mPaint;

    /**
     * 小圆点半径
     */
    private int mCircleRadius;
    /**
     * 屏幕宽度
     */
    private int mScreenWidth;

    /**
     * 存放Tab的集合 Key:导航栏的标题 Fragment:导航页
     */
    private Map mTabs;
    /**
     * View中有getContext()方法,用变量就会
     * 多一个Context引用,会增加一丁点虚拟机的负担吗?
     * 如果不用变量,但是每次都使用getContext(),是不是都要多一层
     * 调用栈,这个怎么权衡,求答案,还是我想多了?
     */
    private Context mContext;

    private ViewPager mViewPager;

    public TabLinearLayout(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public TabLinearLayout(Context context) {
        this(context, null);
    }

    public TabLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mContext = getContext();
        setOrientation(HORIZONTAL);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setStyle(Style.FILL);
        mPaint.setColor(Color.WHITE);
        mPaint.setStrokeCap(Cap.ROUND);

        DisplayMetrics metrics = getResources().getDisplayMetrics();
        mScreenWidth = metrics.widthPixels;
        mCircleRadius = (int) getResources().getDimension(R.dimen.radius);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int tabCount = getChildCount();

        if (tabCount == 0) {
            return;
        }
        /** 不管默认测量结果怎么样,我们都要重新给其宽度赋值*/
        mRealVisibleTabCounts = MAX_VISIBLE_TAB_COUNTS < tabCount ? MAX_VISIBLE_TAB_COUNTS : tabCount;
        // 为每一个子view重新分配mScreenWidth / mRealVisibleTabCounts大小的宽度
        int averageWidth = mScreenWidth / mRealVisibleTabCounts;
        for (int i = 0; i < tabCount; i++) {
            View view = getChildAt(i);
            LinearLayout.LayoutParams params = (android.widget.LinearLayout.LayoutParams) view.getLayoutParams();
            params.weight = 0;
            params.width = averageWidth;
            view.setLayoutParams(params);
        }
    }
    /**
     * 获得Tabs列表
     * @return
     */
    public List getTabs() {
        return new ArrayList(mTabs.values());
    }
    /**
     * 添加一个Tab项,添加一个tab的时候同时给
     * 该视图添加一个TextView
     * @param title
     * @param tab
     */
    public void addTab(String title, Fragment tab) {
        if (mTabs == null) {
            mTabs = new LinkedHashMap<>();
        }
        mTabs.put(title, tab);
        addView(createTabItem(title, mTabs.size() - 1));
    }
    /**
     * 设置ViewPager
     * 同时给其设置OnPageChangeListener监听器。
     * @param viewPager
     */
    public void setViewPager(ViewPager viewPager) {
        mViewPager = viewPager;
        mViewPager.setOnPageChangeListener(this);
    }

    /**
     * 创建一个Tab视图
     * @param title Fragment对应的标题
     * @param index 该Fragme



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Android 高仿华为手机Tab页滑动导航效果

相关文章

  • 2017-05-26组件RecyclerView的应用(一),组件recyclerview
  • 2017-05-26location of the android sdk has not been setup in the preferences,androidpreferences
  • 2017-05-26安卓开源项目周报1214,安卓开源项目1214
  • 2017-05-26BroadcastReceiver--Android广播机制,broadcastreceiver
  • 2017-05-26android studio 图片资源的放置位置,你中枪了吗?
  • 2017-05-26Android 5.0(包含5.0以下版本) 获取栈顶应用程序包名,android包名
  • 2017-05-26android studio 使用checkstyle全攻略
  • 2017-05-26关于JNI的使用方法,JNI使用方法
  • 2017-05-26android滚动公告栏,android公告栏
  • 2017-05-26andorid build tools 19.1,andorid19.1

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • Play 2D games on Nexus 6P running Android N7.1.1 with Daydream View VR headset,n7.1.1headset
    • 杂谈——Android从启动到程序运行发生的事情
    • Android中点击事件的实现方式,android事件
    • GreenDao教程1,greendao教程
    • Android网络编程使用HttpClient访问web站点
    • 硅谷商城3--购物车数据存储器,3--购物车
    • Android中使用开源框架citypickerview实现省市区三级联动选择,
    • android gridview画分割线
    • Native SBS for Android,nativeandroid
    • [android] 手机卫士设备管理权限锁屏,android锁屏

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有