微信底部导航渐变效果-----viewpager&PorterDuffXfermode

实现这个功能主要涉及的知识点有

  1. ViewPager
  2. PorterDuffXfermode
  3. 自定义视图

ViewPager

关于ViewPager需要注意的知识主要是OnPageChangeListener,该接口的三个方法如下

public abstract void onPageScrollStateChanged (int state)

public abstract void onPageScrolled (int position, float positionOffset, int positionOffsetPixels)

public abstract void onPageSelected (int position)

第一个方法onPageScrollStateChanged 中的参数state,有三个可取的值

public static final int SCROLL_STATE_DRAGGING
Constant Value: 1 (0x00000001)

public static final int SCROLL_STATE_IDLE
Constant Value: 0 (0x00000000)

public static final int SCROLL_STATE_SETTLING
Constant Value: 2 (0x00000002)

SCROLL_STATE_DRAGGING:手指按在viewpager上滑动时

SCROLL_STATE_SETTLING:手指松开后,viewpager自动滑动期间

SCROLL_STATE_IDLE:viewpager滑动进入了某个page。

如果你在onPageScrollStateChanged 中输出state的值,你会发现每次都是按顺序打印出“1---2----0”

第二个方法onPageScrolled的三个参数

position:滑动时,屏幕左侧显示的第一个page

positionOffset:滑动比例,值的范围为[0, 1),手指往左滑动,该值递增,反之递减

positionOffsetPixels:滑动距离,和屏幕有关,手指往左滑动,该值递增,反之递减

我们经常需要检查viewpager的滑动方向并作出一些操作,这时你只需要通过position和positionOffset两个值即可实现该功能。

第三个方法onPageSelected的三个参数

position:当前选择的page序号

该方法被调用的时间比较特别,在上面的第一个方法中的“1---2----0”中的2执行之后,onPageSelected就执行,然后执行“1---2----0”中的0。就是手指松开屏幕之后,onPageSelected被执行。

以下在代码中自己重写的一个OnPageChangeListener

/**
 * @author Quinn
 * @date 2015-2-28
 */
public class MainPagerChangeListener implements OnPageChangeListener{

	public interface PagerCallback{
		public void changePageColor(int index, int offset);
	}

	private PagerCallback callback;

	public MainPagerChangeListener(MainActivity mainActivity){
		this.callback  = (PagerCallback)mainActivity;
	}

	//顺序为1-2-0
	@Override
	public void onPageScrollStateChanged(int state) {

	}

	@Override
	public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
		if(positionOffset != 0.0f){
			callback.changePageColor(position+1,  (int)(positionOffset * 255));
			callback.changePageColor(position,  (int)((1-positionOffset) * 255));
		}
	}

	@Override
	public void onPageSelected(int position) {

	}
}

首先我们留一个回调接口PagerCallback,然后在onPageScrolled中执行操作。可以根据position和positionOffset两个值,对两个方向的page进行不同的操作。我们这里进行的操作是改变图标的颜色。

PorterDuffXfermode

先看以下这幅图

微信的底部图案,其原型是一个灰色的图案,在滑动时,会发生颜色渐变,那么怎样使一张图片产生这样的效果呢?其原理是利用PorterDuffXfermode!先看以下这张图片

上述16个图,我们看第二排的第三个,黄色部分代表Dst,蓝色部分代表Src,将Dst覆盖在Src之上,选择"DstIn"模式,就可以合成上述第二排第三张图片。那么,如果Src是一个灰色的图片(图片部分是透明的,像上面微信的四个图标),Dst是一个绿色的矩形,其大小和图片一致。然后将绿色的矩形覆盖在图片之上,选择“DstIn”模式,就能达到将图片设置成绿色的效果。在这个基础上,要对图片进行颜色渐变,只需在viewpager滑动时修改上述Dst矩形的颜色透明度即可。实现代码可以在文章末尾下载源码。博客主要记录实现思路和细节,贴出代码感觉太冗长了。

自定义视图

自定义视图,一般按以下步骤进行

  • 自定义属性
  • 获取属性
  • 重写onMeasure
  • 重写onDraw

我们在自定义底部带文字的图标,自定义属性如下:

路径:XMPP\res\values\attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="FooterTextIcon">
        <attr name="iconSrc" format="reference" />
        <attr name="color" format="color"/>
        <attr name="text" format="string"/>
        <attr name="textSize" format="dimension"/>
    </declare-styleable>

</resources>

这些自定义属性的使用方式如下

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:FooterIcon="http://schemas.android.com/apk/res/com.quinn.xmpp"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.quinn.xmpp.ui.main.MainActivity" >
//省略,,,,
//,,,
//,,,
 <com.quinn.xmpp.ui.widget.FooterTextIcon
            android:id="@+id/chattingIcon"
            android:layout_width="0dip"
            android:layout_height="match_parent"
            android:layout_weight="1"
            FooterIcon:iconSrc="@drawable/ic_action_chat"
            FooterIcon:text="聊天"
            FooterIcon:textSize="12sp"
            android:padding="5dip"
            FooterIcon:color="#ff181818" />
//省略,,,,
//,,,
//,,,
</LinearLayout>

在使用自定义属性时,需要在使用这些自定义属性的布局文件中引入一个命名空间,比如上述代码的第三行,它的格式是:

xmlns:自己起一个名字="http://schemas.android.com/apk/res/应用的包名"

注意,上面代码的最后一部分是应用的包名,而不是某个Activity的包名或者自定义组件对应Java文件的包名

前面自定义属性的attrs.xml中,可以自定义的属性类型(对应上述的format)有以下几种

reference、string、color、dimension、boolean、integer、float、fraction、enum、flag

主要讲讲其中比较常用而且容易混淆的四个

reference的值必须是"@drawable/xxxxxx"

比如上面的

FooterIcon:iconSrc="@drawable/ic_action_chat"

而string,color,dimension的值可以直接写某个值,也可以是引用于资源文件string.xml,color.xml,dimens.xml

比如

            FooterIcon:text="聊天"
            FooterIcon:textSize="12sp"
            android:padding="5dip"
            FooterIcon:color="#ff181818"</span>

也可以写成

            FooterIcon:text="@string/xxxxx"
            FooterIcon:textSize="@dimen/xxxx"
            android:padding="@dimen/xxxx"
            FooterIcon:color="@color/xxxx" />

然后,我们需要在一个地方使用这些属性的值,就是在我们的自定义组件的类文件中。如下:

public class FooterTextIcon extends View {

	//四个属性
	private String text;
	private int themeColor;
	private int textSize;
	private int iconRid;
	//、、、

	/**
	 * @param context
	 */
	public FooterTextIcon(Context context) {
		this(context, null);
	}

	public FooterTextIcon(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	/**
	 * @param context
	 * @param attrs
	 * @param defStyleAttr
	 */
	public FooterTextIcon(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		TypedArray a = context.obtainStyledAttributes(attrs,
				R.styleable.FooterTextIcon);
		iconRid = a.getResourceId(R.styleable.FooterTextIcon_iconSrc, -1);
		text = a.getString(R.styleable.FooterTextIcon_text);
		textSize = (int) a.getDimension(R.styleable.FooterTextIcon_textSize, TypedValue
				.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12,
						getResources().getDisplayMetrics()));
		themeColor = a.getColor(R.styleable.FooterTextIcon_color, Color.parseColor(DEFAULT_CHOSEN_COLOR));
		a.recycle();
                //,,,

	}
        //,,省略,,

}

如上,我们在构造函数中,通过一个TypeArray对象获取各种类型的属性,并且最后调用TypeArray的recycle函数回收内存。一般我们将这些代码放在有三个参数的构造方法中执行,而又一个参数的构造方法直接用this指针调用有两个参数的构造方法,同理,两个的调用三个的。

关于自定义组件的知识可以参考另外两篇博客

android自定义View-------滑动按钮

android自定义View-------为什么重写onMeasure()以及怎么重写

该功能目前应用于我的XMPP项目  https://github.com/Leaking/xmppIM

后续坚持把写这个开源项目使用到的知识都记录在博客里。

时间: 2024-12-28 01:15:35

微信底部导航渐变效果-----viewpager&PorterDuffXfermode的相关文章

Android UI-仿微信底部导航栏布局

现在App基本的标配除了侧滑菜单,还有一个就是底部导航栏,常见的聊天工具QQ,微信,购物App都有底部导航栏,用户可以随便切换看不同的内容,说是情怀也好,用户体验也罢.我们开发的主要的还是讲的是如何如何实现其功能,网上实现的方式无外乎两种,一种是使用tabhost进行切换,一种是直接使用Fragment进行切换,底部导航栏的布局有的使用的是线性布局,有的是使用的RadioGroup,本文中是使用fragment+RadioGroup是实现的,看正文吧: 基础布局 其中主要低 底部导航栏,其他都没

Android——Fragment实例精讲——底部导航栏+ViewPager滑动切换页面

说明: 实现效果: 1- 用ViewPager实现Fragmen之间的切换 2- 底部用RadioGroup实现,更方便的实现图片和字体颜色的改变,更方便的通过RadioButton的点击事件来控制页面切换 原文地址:http://www.runoob.com/w3cnote/android-tutorial-fragment-demo4.html

Android Fragment实现微信底部导航

1.XML布局 (1)主界面 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://

Android学习笔记---使用TabHost实现微信底部导航栏效果

一. TabHost介绍 TabHost组件可以在界面中存放多个选项卡, 很多软件都使用了改组件进行设计; 1. TabHost常用组件 TabWidget : 该组件就是TabHost标签页中上部 或者 下部的按钮, 可以点击按钮切换选项卡; TabSpec : 代表了选项卡界面, 添加一个TabSpec即可添加到TabHost中; -- 创建选项卡 : newTabSpec(String tag), 创建一个选项卡; -- 添加选项卡 : addTab(tabSpec); 2. TabHos

Android底部导航栏

Android UI-仿微信底部导航栏布局 Android基础入门教程——5.2.1 Fragment实例精讲——底部导航栏的实现(方法1)

android高仿微信底部渐变导航栏

最近有很多人微信底部的变色卡片导航是怎么做的,我在网上看了好几个例子,都是效果接近,都存有一些差异,自己琢磨也做了一个,几乎99%的还原,效果还不错吧 仔细观察微信图片,发现他有两部分内容,外面的边框和里面的内容,内容的颜色由绿变为透明,这部分可以直接改变透明度,外面的边框,颜色在灰色和绿色之间变化,就不能简单的改变透明度了,ImageView的tint 为我们提供了可行方案,tint可以为图标着色,既可以在xml中,也可以在代码中设置,一共有16中模式,分别为 在xml中设置:直接添加tint

Android仿小米商城底部导航栏之二(BottomNavigationBar、ViewPager和Fragment的联动使用)

简介 在前文<Android仿小米商城底部导航栏(基于BottomNavigationBar)>我们使用BottomNavigationBar控件模仿实现了小米商城底部导航栏效果.接下来更进一步的,我们将通过BottomNavigationBar控件和ViewPager空间的联动使用来实现主界面的滑动导航. 导航是移动应用最重要的方面之一,对用户体验是良好还是糟糕起着至关重要的作用.好的导航可以让一款应用更加易用并且让用户快速上手.相反,糟糕的应用导航很容易让人讨厌,并遭到用户的抛弃.为了打造

微信小程序把玩(三)tabBar底部导航

原文:微信小程序把玩(三)tabBar底部导航 tabBar相对而言用的还是比较多的,但是用起来并没有难,在app.json中配置下tabBar即可,注意tabBar至少需要两个最多五个Item选项 主要属性: 对于tabBar整体属性设置: 对于tabBar中每个Item属性设置: 下面是官网一张图对tabBar描述: app.json的配置相对就简单了:

微信小程序-自定义底部导航

代码地址如下:http://www.demodashi.com/demo/14258.html 一.前期准备工作 软件环境:微信开发者工具 官方下载地址:https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html 1.基本需求. 实现用户自定义底部导航 2.案例目录结构 二.程序实现具体步骤 1.自定义nav.wxml代码 <template name="nav"> <view class=&quo