导航栏特效-新闻类APP(比网易,今日头条好看)

好久没有写文章了,慢慢的自己工作中遇到的问题不做积累,下次遇到还会忘。哎。。。。

周日无聊的单身程序员-唯有程序你懂的...

写着程序听着歌也是极好的!!

最近工作中要实现类似 今日头条等新闻类APP顶部导航条的效果 ,不过我们这效果切换时要加上文字颜色的渐变和缩放

我不会弄动态图片啊,求各位会的教俺下:

一:分析

今天我们要实现这种特效。

用到的开源项目有:master-nineoldandroids-library.jar这个jar包,这个是向下兼容的jar包,包括android一系列的动画。

首先我们说一下这种 日头条等新闻类APP 的基本实现是ViewPage+Fragment+HorizontalScrollView

我们今天说的就是这个HorizontalScrollView的特效。

实现原理图:

相信大家已经明白了大概

就是:最初时我们 初始化textview  并把选中的和正常的textview 初始化。就是上图中的framelayout中的2个textview 放到集合 HashMap<String, View>()中。用于保持所有textview的状态。

至于代码怎么写呢?!

android系统给我们提供了一个叫PagerSlidingTabStrip的类,在v4包中。我们把java中考出来放到我们的小明中,修改其中的代码就可以。

我们通过viewpage来控制导航条。把viewpage传到PagerSlidingTabStrip中,并设置监听器,代码如下:

public void setViewPager(ViewPager pager) {
		this.pager = pager;

		if (pager.getAdapter() == null) {
			throw new IllegalStateException(
					"ViewPager does not have adapter instance.");
		}

		pager.setOnPageChangeListener(pageListener);

		notifyDataSetChanged();
	}

二、获取用户切换时当前View和切换至的目的View。

ViewPager也需要监听用户的手势,所以肯定提供了某个方法。于是纵观ViewPager的方法,发现了一个叫做 onPageScrolled(int position, float positionOffset, int positionOffsetPixels)的方法~~

没错就是这个方法:在页面滚动时调用~

下面仔细研究下这几个参数:

直接说测试结果:

在非第一页与最后一页时,滑动到下一页,position为当前页位置;滑动到上一页:position为当前页-1

positionOffset 滑动到下一页,[0,1)区间上变化;滑动到上一页:(1,0]区间上变化

positionOffsetPixels这个和positionOffset很像:滑动到下一页,[0,宽度)区间上变化;滑动到上一页:(宽度,0]区间上变化

第一页时:滑动到上一页position=0 ,其他基本为0 ;最后一页滑动到下一页 position为当前页位置,其他两个参数为0

豁然发现,我们需要的步骤的第二步解决了,positionOffset很适合作为,渐变,缩放的控制参数;positionOffsetPixels则可以作为平移等的控制参数。

那么如何获得当前View和目的View呢:

分享几个我的歧途:

1、【错误】我通过getChildAt(position),getChildAt(position+1),getChildAt(position-1)获得滑动时,左右的两个View;乍一看,还真觉得不错~~~在代码写出来,再乍效果也出不来~~错误原因:我们忽略一个特别大的东西,ViewPager的机制,滑动时动态加载和删除View,ViewPager其实只会维持2到3个View,而position的范围基本属于无限~~

2、【错误】我通过getCurrentItem获得当前的位置,然后+1,-1获得后一个或者前一个~~正在窃喜,赶快代码改过来,效果怎么也不对,乱七八糟的~~仔细观察日志,这个getCurrentItem当用户手指离开的屏幕,Page还在动画执行时,就改变了~~难怪~整个滑动过程并不是固定的~~唉,心都碎了~

3、【错误】position在整个滑动的过程中是不变化的,而且ViewPager会保存2个或3个View;那么我考虑,如果是第一页、或者最后一页那么我取getChildAt(0)和getChildAt(1),如果在其他页面则为getChildAt(0),getChildAt(2),然后经过一系列的变化~我想这会总该对了吧,于是我遇到第一问题,第一页的时候,不管左右position都为0,尼玛,这哪个为左View,哪个为右View~~

说了这么多错误,大家可以绕过这些弯路,也能从这些弯路里面看出点什么~

下面说正确的,其实ViewPager在添加一个View或者销毁一个View时,是我们自己的PageAdapter中控制的,于是我们可以在ViewPager里面维系一个HashMap<Position,View>,然后滑动的时候,通过get(position)取出,比如上述效果,始终是右边的View变化,要么从小到大,要么从大到小

那么滑倒下一页:左边的View:map.get(position) ,右边的View : map.get(position+1) . 

那么滑倒上一页:左边的View : map.get(position) , 右边的View : map.get(position+1) , 一样的,因为滑到上一页,position为当前页-1

关键代码:

<pre name="code" class="java">	private class PageListener implements OnPageChangeListener {
		private int oldPosition = 0;

		@Override
		public void onPageScrolled(int position, float positionOffset,
				int positionOffsetPixels) {
			currentPosition = position;
			currentPositionOffset = positionOffset;

			scrollToChild(position, (int) (positionOffset * tabsContainer
					.getChildAt(position).getWidth()));

			invalidate();

			if (delegatePageListener != null) {
				delegatePageListener.onPageScrolled(position, positionOffset,
						positionOffsetPixels);
			}

			if (mState == State.IDLE && positionOffset > 0) {
				oldPage = pager.getCurrentItem();
				mState = position == oldPage ? State.GOING_RIGHT
						: State.GOING_LEFT;
			}
			boolean goingRight = position == oldPage;
			if (mState == State.GOING_RIGHT && !goingRight)
				mState = State.GOING_LEFT;
			else if (mState == State.GOING_LEFT && goingRight)
				mState = State.GOING_RIGHT;

			float effectOffset = isSmall(positionOffset) ? 0 : positionOffset;

			View mLeft = tabsContainer.getChildAt(position);
			View mRight = tabsContainer.getChildAt(position + 1);

			if (effectOffset == 0) {
				mState = State.IDLE;
			}

			if (mFadeEnabled)
				animateFadeScale(mLeft, mRight, effectOffset, position);

		}

		@Override
		public void onPageScrollStateChanged(int state) {
			if (state == ViewPager.SCROLL_STATE_IDLE) {
				scrollToChild(pager.getCurrentItem(), 0);
				mFadeEnabled = true;
			}

			if (delegatePageListener != null) {
				delegatePageListener.onPageScrollStateChanged(state);
			}
		}

		@Override
		public void onPageSelected(int position) {
			// selectedPosition = position;
			// updateTabStyles();
			currentPosition = position;

			// set old view statue
			ViewHelper.setAlpha(tabViews.get(oldPosition).get("normal"), 1);
			ViewHelper.setAlpha(tabViews.get(oldPosition).get("selected"), 0);
			View v_old = tabsContainer.getChildAt(oldPosition);
			ViewHelper.setPivotX(v_old, v_old.getMeasuredWidth() * 0.5f);
			ViewHelper.setPivotY(v_old, v_old.getMeasuredHeight() * 0.5f);
			ViewHelper.setScaleX(v_old, 1f);
			ViewHelper.setScaleY(v_old, 1f);

			// set new view statue
			ViewHelper.setAlpha(tabViews.get(position).get("normal"), 0);
			ViewHelper.setAlpha(tabViews.get(position).get("selected"), 1);
			View v_new = tabsContainer.getChildAt(position);
			ViewHelper.setPivotX(v_new, v_new.getMeasuredWidth() * 0.5f);
			ViewHelper.setPivotY(v_new, v_new.getMeasuredHeight() * 0.5f);
			ViewHelper.setScaleX(v_new, 1 + ZOOM_MAX);
			ViewHelper.setScaleY(v_new, 1 + ZOOM_MAX);

			if (delegatePageListener != null) {
				delegatePageListener.onPageSelected(position);
			}
			// oldPosition = selectedPosition;
			oldPosition = currentPosition;

		}

	}

可以看到代码:缩放view很关键:

View v_old = tabsContainer.getChildAt(oldPosition);
			ViewHelper.setPivotX(v_old, v_old.getMeasuredWidth() * 0.5f);
			ViewHelper.setPivotY(v_old, v_old.getMeasuredHeight() * 0.5f);
			ViewHelper.setScaleX(v_old, 1f);
			ViewHelper.setScaleY(v_old, 1f);

找到view的中心点即:setPivotX setPivotY 然后对X轴Y轴缩放。1为原始大小。>1放大,<1  且>0 缩小。

关键代码是:onPageScrolled 方法的底2个参数positionOffset 滑动的百分比。

渐变通过animateFadeScale这个方法控制:

	protected void animateFadeScale(View left, View right,
			float positionOffset, int position) {

		if (mState != State.IDLE) {
			if (left != null) {
				ViewHelper.setAlpha(tabViews.get(position).get("normal"),
						positionOffset);
				ViewHelper.setAlpha(tabViews.get(position).get("selected"),
						1 - positionOffset);

				float mScale = 1 + ZOOM_MAX - ZOOM_MAX * positionOffset;

				ViewHelper.setPivotX(left, left.getMeasuredWidth() * 0.5f);
				ViewHelper.setPivotY(left, left.getMeasuredHeight() * 0.5f);
				ViewHelper.setScaleX(left, mScale);
				ViewHelper.setScaleY(left, mScale);

			}
			if (right != null) {
				ViewHelper.setAlpha(tabViews.get(position + 1).get("normal"),
						1 - positionOffset);
				ViewHelper.setAlpha(tabViews.get(position + 1).get("selected"),
						positionOffset);

				float mScale = 1 + ZOOM_MAX * positionOffset;

				ViewHelper.setPivotX(right, right.getMeasuredWidth() * 0.5f);
				ViewHelper.setPivotY(right, right.getMeasuredHeight() * 0.5f);
				ViewHelper.setScaleX(right, mScale);
				ViewHelper.setScaleY(right, mScale);

			}
		}
	}

在你activity/引用的地方 中你可以直接设置TAB的颜色大小,正常色,选中色等。EG:

/**
	 * 对PagerSlidingTabStrip的各项属性进行赋值。
	 */
	private void setTabsValue() {
		// 设置Tab是自动填充满屏幕的
		tabs.setShouldExpand(true);
		// 设置Tab的分割线是透明的
		tabs.setDividerColor(Color.TRANSPARENT);
		// 设置Tab底部线的高度
		tabs.setUnderlineHeight((int) TypedValue.applyDimension(
				TypedValue.COMPLEX_UNIT_DIP, 1, dm));
		// 设置Tab Indicator的高度
		tabs.setIndicatorHeight((int) TypedValue.applyDimension(
				TypedValue.COMPLEX_UNIT_DIP, 4, dm));
		// 设置Tab标题文字的大小
		tabs.setTextSize((int) TypedValue.applyDimension(
				TypedValue.COMPLEX_UNIT_SP, 16, dm));
		// 设置Tab Indicator的颜色
		tabs.setIndicatorColor(Color.parseColor("#45c01a"));
		// 设置选中Tab文字的颜色 (这是我自定义的一个方法)
		tabs.setSelectedTextColor(Color.parseColor("#45c01a"));
		//设置正常Tab文字的颜色 (这是我自定义的一个方法)
		tabs.setTextColor(Color.parseColor("#C231C7"));
		// 取消点击Tab时的背景色
		tabs.setTabBackground(0);
	}

备注:该代码是在之前的一个模仿android-微信主界面上改的,可能会有多余的类,忘理解!!

源代码

时间: 2024-08-15 07:42:33

导航栏特效-新闻类APP(比网易,今日头条好看)的相关文章

css小案例:导航栏特效

css小案例:导航栏特效,实现如下图所示效果: 首先可以将html代码写出: 1 <nav class="cl-effect-1"> 2 <a href="#">Umbrella</a> 3 <a href="#">Ineffable</a> 4 <a href="#">Lilt</a> 5 <a href="#"&g

高仿新闻类APP频道管理功能,ItemTouchHelper的实践

转载请标明出处: http://blog.csdn.net/iamzgx/article/details/52843653 在上篇博客 简单仿TabLayout实现个性化Tab,让Tab展现多样化,通过HorizontalScrollView实现了类似TabLayout的功能,并且进行了红点提醒,数字提醒的拓展功能.这种功能在新闻类APP是很常见的,还有一种很常见的功能在上一篇博客结尾也提到过,也就是频道管理的功能.以常用的今日头条为例,频道管理功能效果图如下 仔细玩下这里的功能,这里最难的点应

jquery-仿flash的一个导航栏特效

演示地址:http://itxiaoming.sinaapp.com/demo05/demo.html Html代码   <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <title>demo01</title> <link rel="stylesheet" type=

导航栏特效 仅供自己学习使用

  <!DOCTYPE html>   <html>   <head>   <meta charset="UTF-8">   <title></title>   <style>       * {   margin: 0;   padding: 0;   }       body {   background-color: moccasin;   }       .list {   list-style

xcode 左边导航栏中,类文件后面的标记“A”,&quot;M&quot;,&quot;?&quot;……等符号的含义???

"M" = Locally modified "U" = Updated in repository "A" = Locally added "D" = Locally deleted "I" = Ignored "R" = Replaced in the repository "–" "=" The contents of the folder 

android——仿网易今日头条等自定义频道listview 或者grideview等item上移到另一个view中

转载请注明出处: www.cnblogs.com/shoneworn 我这里只是简单的用了两个listview来实现的,先上效果图.比较粗糙.预留了自定义的空间. 思路: 从上图应该可以看的出来.就是上下两个listview.点击下面的ltem.会动态的移动到上一个listview的最后.上面的listview 为listview1,下面的为listview2.  点击listview2,获取到view ,设置一个动画,移动到listview1 ,listview2中删除被点的item.list

CSS实现动画特效导航栏

0 写在前面 今天用纯CSS编写了一种带有特效的导航栏,一方面巩固熟悉了导航栏的一般写法,另一方面练习了CSS3的一些新特性. 1 实现效果 当鼠标划过时,实现了一种动态百叶窗效果. 2 实现细节 2-0 导航栏基本架构 首先复习导航栏的基本架构,导航栏的实现,采用的是ul-li的结构,为了能够实现导航效果,可以在li内部增加一个a标签. 实现导航栏结构的html代码如下: 1 <div class="container"> 2 <ul class="men

新闻类应用后台耗电大调查!哪个应用最省电?

你以为除了最新打开的应用之外, 其他应用便能安静乖巧? 你以为手机灭屏之后, 应用就能随即入眠.悄无声息? No!No!No! 事实是这时候, 应用后台的表现也是大相径庭-- 它们中间既有超级省电的乖宝宝, 也有在后台淘气耗电的熊孩子! 那么,作为一枚不愿错过任何热点的 新闻类APP吃瓜群众, 如何才能一边知晓天下新闻, 一边让自己的爱机能量满格? 选择哪款应用,才可能让后台耗电降到最低? 华为终端开放实验室发布 <新闻类应用后台耗电大调查>, 带你走进那些后台耗电的秘密! 测试背景说明 数据

UI: 使用 UIBarButtonItem 给导航栏添加按钮

问题: 希望将按钮添加到导航栏中 1.导航栏属于 UINavigationBar 类,你可以再任何时候创建它,并将它添加到任意的 view 中. 2.创建一个导航按钮,须要做一下工作: 创建一个 UIBarButtonItem 实例. 使用视图控制器的 navigationItem 属性将按钮添加到视图控制器的导航栏中,. NavigationItem 属性允许我们与导航栏进行交互.这个属性自身有两个属性,分别为 rightBarButtonItem 和 leftBarButtonItem.这两