博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Making Your ActionBar Not Boring
阅读量:5875 次
发布时间:2019-06-19

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

      这篇文章转自国外一个技术大牛的。首先感谢这位大牛的无私奉献。

Android应用中有一名为 Google书报摊的应用,他实现了一种新的ActionBar风格。效果如以下的动画,因为上传图片大小的限制。对图片做了处理。效果受到了影响,能够查看会有清晰流畅的动画效果。

      当用户初始进入该界面的时候,为一个透明的 ActiionBar ,这样利用充分的空间显示大图片,假设用户滚动页面须要查看内容的时候,则大图收缩到 ActionBar 中。

                

    这个的主要优势是使ActionBar和内容完美的结合在一起。整个操作看起来浑然天成,给人一种新鲜的感觉。这篇文章将会解说ActionBar效果和 动画效果的实现。

The ActionBar trick

Styles:

第一步先制作合适的Style,这里须要使用ActionBar的并设置透明的ActionBar背景。

布局结构

    布局结构是很重要,基本的布局是一个由ListView和还有一个的FrameLayout(即题图)组成的FrameLayout。

题图包括两个图片。一个背景大图(即header_picture),一个logo图像(即header_logo)。

    通过在 ListView 上加入一个高度和 题图一样高的 虚拟 header view 来实现该动画。 能够用一个布局文件来作为该虚拟 header 的 view。

使用inflate加入上虚拟 header view

mFakeHeader = getLayoutInflater().inflate(R.layout.fake_header, mListView, false);mListView.addHeaderView(mFakeHeader);

获取Scroll位置

布局文件搞定,须要计算出ListView的滚动位置

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;}

特别提示。假设listview第一个可视视图位置大于1。须要计算虚拟视图的高度。

移动题头

    伴随着listview的滚动,你须要移动题头,以跟踪虚拟题头的移动。

这些移动以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));        }    });

Title渐变

     这里的Title有个渐变效果,他是怎么实现的呢,首先获取到这个view,使用的方法。

private TextView getActionBarTitleView() {    int id = Resources.getSystem().getIdentifier("action_bar_title", "id", "android");    return (TextView) findViewById(id);}
    然后设置初始的 alpha 值。

getActionBarTitleView().setAlpha(0f);

在 ListView 滚动的时候,计算该 alpha 值。

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 值的变化方程式为 f(x) = 5x-4。

关于该方程式參考:

    而关于标题的淡出提供了一个更好的方案。

    在该方案中无需获取 ActionBar title view。使用一个具有自己定义  的    。然后在该    上设置文字的 Alpha 值。

public class AlphaForegroundColorSpan extends ForegroundColorSpan {    private float mAlpha;    public AlphaForegroundColorSpan(int color) {        super(color);        }        […]        @Override        public void updateDrawState(TextPaint ds) {                ds.setColor(getAlphaColor());        }    public void setAlpha(float alpha) {        mAlpha = alpha;    }    public float getAlpha() {        return mAlpha;    }    private int getAlphaColor() {        int foregroundColor = getForegroundColor();        return Color.argb((int) (mAlpha * 255), Color.red(foregroundColor), Color.green(foregroundColor), Color.blue(foregroundColor));    }}

    滚动的时候改动该    的 Alpha值并设置为 Title,使用相同的 AlphaForegroundColorSpan 和 SpannableString 避免频繁 GC 来提升性能。

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            setTitleAlpha(clamp(5.0F * ratio – 4.0F, 0.0F, 1.0F));        }    });private void setTitleAlpha(float alpha) {        mAlphaForegroundColorSpan.setAlpha(alpha);        mSpannableString.setSpan(mAlphaForegroundColorSpan, 0, mSpannableString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);        getActionBar().setTitle(mSpannableString);    }

移动&缩放icon

先获取该 图标 View, 然后在 ActionBar 上设置一个透明的图标。

private ImageView getActionBarIconView() {    return (ImageView) findViewById(android.R.id.home);}
ActionBar actionBar = getActionBar();actionBar.setIcon(R.drawable.ic_transparent);

      当 ListView 滚动时候。依据 header 的高度来移动和缩放图标。该缩放和位移是依据两个图标的位置关系和大小关系来计算的。

代码例如以下:

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);        }    });

    注意你也能够用  来让动画看起来更平滑一些。

    在该演示样例代码中还包括了一个 Ken Burns 动画,使题图能够移动。能够參考事实上现:

完整演示样例项目

总结:

View的同步Scroll总有他的类似之处,大家要多思考。
       As it’s said , it’s always (with a few different details) the same trick called synchronized scrolling. The true genius of this effect is to have thought about it!

參考:

http://flavienlaurent.com/blog/2013/11/20/making-your-action-bar-not-boring/

你可能感兴趣的文章
C语言的简单函数定义与调用
查看>>
二维码
查看>>
7-24
查看>>
spring中的JdbcTemplate简单记录
查看>>
pygame连载
查看>>
寒冰linux视频教程笔记12 计划任务
查看>>
在C盘上安装安装Windows Server 2008
查看>>
Servlet3.1 edr 规范中文版下载
查看>>
Magento支付宝插件V6.1旗舰版发布,支持即时到账、担保交易,新增订单重新支付功能!...
查看>>
基于Annotation方式的SpringMVC4+Spring4+Hibernate4
查看>>
我的友情链接
查看>>
git add 项目文件 改动
查看>>
GAP
查看>>
C/C++中的引用和指针
查看>>
CISCO PIX515 在企业应用中的布署
查看>>
学习笔记-Exchange Web Service API-概述
查看>>
idea创建Web项目
查看>>
zabbix管理一之zabbix的简介
查看>>
VRP命令行基础-路由交换原理8-【HCNA笔记】
查看>>
我的友情链接
查看>>