博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
实现一个与内容合二为一的ActionBar动画效果
阅读量:5758 次
发布时间:2019-06-18

本文共 4413 字,大约阅读时间需要 14 分钟。

实现一个与内容合二为一的ActionBar动画效果,让你的actionbar更生动。以下是效果图:

这样的效果的优点是让actionbar也成为了内容的一部分,实际应用的效果比图片展示的效果要好,除了actionbar渐渐出现的效果外。背景图片另一种称之为 的动态效果。

以下解说实现过程。

设置actionbar的样式。我们须要例如以下两点:

1.actionbar是透明的。

2.开启overlay mode模式

布局

布局是实现的关键,FrameLayout中包括一个ListView以及另外一个FrameLayout(头部,显示图片的地方,这里我们称之为header)。header中包括了两个ImageView,一个用于显示背景图片,一个用于显示logo。这个logo会跟着listView的滚动而变化。并终于跑到actionbar中。

这里的技巧是给Listview加入一个伪造的header,而且将它的高度设置成真实
header的高度

伪造header的xml代码
将他inflate后加入到ListView中:
mFakeHeader = getLayoutInflater().inflate(R.layout.fake_header, mListView, false);mListView.addHeaderView(mFakeHeader);
获得滚动位置。这段代码是从stackOverflow上摘抄的:
public int getScrollY() {    View c = mListView.getChildAt(0);    if (c == null) {        return 0;    }    int firstVisiblePosition = mListView.getFirstVisiblePosition();    int top = c.getTop();    int headerHeight = 0;    if (firstVisiblePosition >= 1) {        headerHeight = mPlaceHolderView.getHeight();    }    return -top + firstVisiblePosition * c.getHeight() + headerHeight;}

移动header的位置

当ListView滚动的时候,你必须移动header的位置让他和伪造的ListView header保持同步,注意移动到了actionbar的边界为止。

mListView.setOnScrollListener(new AbsListView.OnScrollListener() {        @Override        public void onScrollStateChanged(AbsListView view, int scrollState) {        }        @Override        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {            int scrollY = getScrollY();            //sticky actionbar            mHeader.setTranslationY(Math.max(-scrollY, mMinHeaderTranslation));        }    });

标题的渐变

actionbar标题文字的出现是渐变的。而标题文字所在的TextView控件能够通过Resource的getIdentifier方法获得。

private TextView getActionBarTitleView() {    int id = Resources.getSystem().getIdentifier("action_bar_title", "id", "android");    return (TextView) findViewById(id);}
初始化的时候将它的透明度设置为0:
getActionBarTitleView().setAlpha(0f);
ListView滚动的时候这个透明度变化的根据是header移动距离的一个比值ratio:
mListView.setOnScrollListener(new AbsListView.OnScrollListener() {        @Override        public void onScrollStateChanged(AbsListView view, int scrollState) {        }        @Override        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {            float ratio = clamp(mHeader.getTranslationY() / mMinHeaderTranslation, 0.0f, 1.0f);            //actionbar title alpha            getActionBarTitleView().setAlpha(clamp(5.0F * ratio - 4.0F, 0.0F, 1.0F));        }    });

Alpha values: f(x) = 5x-4

clamp是一个主要的数学计算公式:

public static float clamp(float value, float max, float min) {    return Math.max(Math.min(value, min), max);}

应用图标和logo的移动和缩放

首先你要获得图标所在的ImageView:

private ImageView getActionBarIconView() {    return (ImageView) findViewById(android.R.id.home);}
设置一个透明的图标
ActionBar actionBar = getActionBar();actionBar.setIcon(R.drawable.ic_transparent);
然后在ListView滑动的过程中依据header的移动比率相应用图标和logo移动与缩放。在这个过程中通过获得应用图标和header中的logo在屏幕上的矩形区域来推断该怎样移动与缩放。

mListView.setOnScrollListener(new AbsListView.OnScrollListener() {        @Override        public void onScrollStateChanged(AbsListView view, int scrollState) {        }        @Override        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {            float ratio = clamp(mHeader.getTranslationY() / mMinHeaderTranslation, 0.0f, 1.0f);            //move & scale            interpolation = mAccelerateDecelerateInterpolator.getInterpolation(ratio);            View actionBarIconView = getActionBarIconView();            getOnScreenRect(mRect1, mHeaderLogo);            getOnScreenRect(mRect2, actionBarIconView);            float scaleX = 1.0F + interpolation  (mRect2.width() / mRect1.width() – 1.0F);            float scaleY = 1.0F + interpolation  (mRect2.height() / mRect1.height() – 1.0F);            float translationX = 0.5F  (interpolation  (mRect2.left + mRect2.right – mRect1.left – mRect1.right));            float translationY = 0.5F  (interpolation  (mRect2.top + mRect2.bottom – mRect1.top – mRect1.bottom));            mHeaderLogo.setTranslationX(translationX);            mHeaderLogo.setTranslationY(translationY – mHeader.getTranslationY());            mHeaderLogo.setScaleX(scaleX);            mHeaderLogo.setScaleY(scaleY);        }    });
注:对上面的代码,我自己的理解是应用图标至始至终都没有显示,仅仅是他的位置被header中的logo占领了。

代码下载:

译文原文:

转载地址:http://oivkx.baihongyu.com/

你可能感兴趣的文章
Android图形显示系统——下层显示4:图层合成上(合成原理与3D合成)
查看>>
Windows 10 技术预览
查看>>
Tomcat http跳转https
查看>>
一个自动布署.net网站的bat批处理实例
查看>>
tomcat 安装
查看>>
我的友情链接
查看>>
Centos6.6安装选包及基础场景说明
查看>>
java基础面试题-1
查看>>
深克隆与序列化效率的比较
查看>>
lamp+nginx代理+discuz+wordpress+phpmyadmin搭建一
查看>>
nagios监控使用139邮箱报警
查看>>
Windows Phone 7 中各种Task解说(启动器与选择器)
查看>>
罗森伯格助力2011年中国智能建筑技术发展应用论坛哈尔滨站
查看>>
网络割接
查看>>
windows server 2016 活动目录(二)
查看>>
openstack G版 修改vm的flavor级别
查看>>
python_控制台输出带颜色的文字方法
查看>>
java泛型中特殊符号的含义
查看>>
一秒 解决 ERROR 1044 (42000): Access denied for user ''@'localhost' to database 'mysql 问题
查看>>
Android组件化最佳实践 ARetrofit原理
查看>>