文档章节

图片位移缩小到标题栏

lsy999
 lsy999
发布于 2017/04/26 20:29
字数 1186
阅读 34
收藏 0
点赞 0
评论 0

为了这个我纠结好好久好久,废话不多说 直接上代码

其实只需要两个java类和一个xml布局

首先在main的xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.design.widget.AppBarLayout

        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_tool_bar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:contentScrim="@color/bar_orange"
            app:expandedTitleGravity="bottom|center_horizontal"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

            <ImageView
                android:id="@+id/iv_head"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="fitXY"
                android:src="@drawable/info_img_pic"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.6" />

            <!-- 设置app:navigationIcon="@android:color/transparent"给头像预留位置 -->
            <android.support.v7.widget.Toolbar
                android:id="@+id/tool_bar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="@color/bar_orange"
                app:theme="@style/ThemeOverlay.AppCompat.Dark">
                <LinearLayout
                    android:orientation="horizontal"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent">
                    <ImageView
                        android:layout_gravity="center"
                        android:id="@+id/main.textview.title"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:gravity="left"
                        android:background="@drawable/tab_btn_eyes" />

                </LinearLayout>
                </android.support.v7.widget.Toolbar>
        </android.support.design.widget.CollapsingToolbarLayout>



    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <include layout="@layout/fragment_home_layout_liao" />
这个是下面的一个

    </android.support.v4.widget.NestedScrollView>

    <!-- layout_anchor属性5.0以上需要设置为CollapsingToolbarLayout,不然头像最后会被覆盖 -->
    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/cl_home_xtx"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_margin="16dp"
        android:src="@drawable/common_img_user"
        app:border_color="@android:color/white"
        app:border_width="1dp"
        app:layout_anchor="@id/collapsing_tool_bar"
        app:layout_anchorGravity="center_vertical|center_horizontal|"
        app:layout_behavior="lib.view.touxiang.AvatarImageBehavior" />这一行很重要


</android.support.design.widget.CoordinatorLayout>

下面是AvatarImageBehavior

package lib.view.touxiang;

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.CoordinatorLayout;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;

import de.hdodenhof.circleimageview.CircleImageView;

/**
 * Created by lsy on 2017/4/25.
 */

public class AvatarImageBehavior extends CoordinatorLayout.Behavior<CircleImageView> {

    // 缩放动画变化的支点
    private static final float ANIM_CHANGE_POINT = 0.2f;

    private Context mContext;
    // 整个滚动的范围
    private int mTotalScrollRange;
    // AppBarLayout高度
    private int mAppBarHeight;
    // AppBarLayout宽度
    private int mAppBarWidth;
    // 控件原始大小
    private int mOriginalSize;
    // 控件最终大小
    private int mFinalSize;
    // 控件最终缩放的尺寸,设置坐标值需要算上该值
    private float mScaleSize;
    // 原始x坐标
    private float mOriginalX;
    // 最终x坐标
    private float mFinalX;
    // 起始y坐标
    private float mOriginalY;
    // 最终y坐标
    private float mFinalY;
    // ToolBar高度
    private int mToolBarHeight;
    // AppBar的起始Y坐标
    private float mAppBarStartY;
    // 滚动执行百分比[0~1]
    private float mPercent;
    // Y轴移动插值器
    private DecelerateInterpolator mMoveYInterpolator;
    // X轴移动插值器
    private AccelerateInterpolator mMoveXInterpolator;
    // 最终变换的视图,因为在5.0以上AppBarLayout在收缩到最终状态会覆盖变换后的视图,所以添加一个最终显示的图片
    private CircleImageView mFinalView;
    // 最终变换的视图离底部的大小
    private int mFinalViewMarginBottom;


    public AvatarImageBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        mMoveYInterpolator = new DecelerateInterpolator();
        mMoveXInterpolator = new AccelerateInterpolator();

    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, CircleImageView child, View dependency) {
        return dependency instanceof AppBarLayout;
    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, CircleImageView child, View dependency) {

        if (dependency instanceof AppBarLayout) {
            _initVariables(child, dependency);


            mPercent = (mAppBarStartY - dependency.getY()) * 1.0f / mTotalScrollRange;
            Log.e("ff", "appnarStart: " + mAppBarStartY + "dependey: " + dependency.getY() + " prencernt: " + mPercent);

            float percentY = mMoveYInterpolator.getInterpolation(mPercent);
            AnimHelper.setViewY(child, mOriginalY, mFinalY - mScaleSize, percentY);

            if (mPercent > ANIM_CHANGE_POINT) {
                float scalePercent = (mPercent - ANIM_CHANGE_POINT) / (1 - ANIM_CHANGE_POINT);
                float percentX = mMoveXInterpolator.getInterpolation(scalePercent);
                AnimHelper.scaleView(child, mOriginalSize, mFinalSize, scalePercent);
                AnimHelper.setViewX(child, mOriginalX, mFinalX - mScaleSize, percentX);
            } else {
                AnimHelper.scaleView(child, mOriginalSize, mFinalSize, 0);
                AnimHelper.setViewX(child, mOriginalX, mFinalX - mScaleSize, 0);
            }
            if (mFinalView != null) {
                if (percentY == 1.0f) {
                    // 滚动到顶时才显示
                    mFinalView.setVisibility(View.VISIBLE);
                } else {
                    mFinalView.setVisibility(View.GONE);
                }
            }
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && dependency instanceof CollapsingToolbarLayout) {
            // 大于5.0才生成新的最终的头像,因为5.0以上AppBarLayout会覆盖变换后的头像
            if (mFinalView == null && mFinalSize != 0 && mFinalX != 0) {
                mFinalView = new CircleImageView(mContext);
                mFinalView.setVisibility(View.GONE);
                // 添加为CollapsingToolbarLayout子视图
                ((CollapsingToolbarLayout) dependency).addView(mFinalView);
                FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mFinalView.getLayoutParams();
                // 设置大小
                params.width = mFinalSize;
                params.height = mFinalSize;
                // 设置位置,最后显示时相当于变换后的头像位置
                params.gravity = Gravity.BOTTOM;
                params.leftMargin = (int) mFinalX;
                params.bottomMargin = mFinalViewMarginBottom;
                mFinalView.setLayoutParams(params);
                mFinalView.setImageDrawable(child.getDrawable());
                mFinalView.setBorderColor(child.getBorderColor());
                int borderWidth = (int) ((mFinalSize * 1.0f / mOriginalSize) * child.getBorderWidth());
                mFinalView.setBorderWidth(borderWidth);
            }
        }

        return true;
    }

    /**
     * 初始化变量
     *
     * @param child
     * @param dependency
     */
    private void _initVariables(CircleImageView child, View dependency) {

        if (mToolBarHeight == 0) {
            mToolBarHeight = getToolBarHeight();
        }
        if (mFinalSize == 0) {
            mFinalSize = getToolBarHeight();
        }
        if (mFinalX == 0) {
            mFinalX = getScreenWidth(mContext) / 2 - mFinalSize / 2;

        }
        if (mAppBarHeight == 0) {
            mAppBarHeight = dependency.getHeight();
            mAppBarStartY = dependency.getY();
        }
        if (mTotalScrollRange == 0) {
            mTotalScrollRange = ((AppBarLayout) dependency).getTotalScrollRange();
        }
        if (mOriginalSize == 0) {
            mOriginalSize = child.getWidth();
        }
        if (mFinalSize == 0) {
            mFinalSize = getToolBarHeight();
        }
        if (mAppBarWidth == 0) {
            mAppBarWidth = dependency.getWidth();
        }
        if (mOriginalX == 0) {
            mOriginalX = child.getX();
        }
        if (mOriginalY == 0) {
            mOriginalY = child.getY();
        }
        if (mFinalY == 0) {
            if (mToolBarHeight == 0) {
                mToolBarHeight = getToolBarHeight();
            }
            mFinalY = (getToolBarHeight() - mFinalSize) / 2;
        }
        if (mScaleSize == 0) {
            mScaleSize = (mOriginalSize - mFinalSize) * 1.0f / 2;
        }
        if (mFinalViewMarginBottom == 0) {
            mFinalViewMarginBottom = (mToolBarHeight - mFinalSize) / 2;
        }
    }

    private int getToolBarHeight() {
        int[] attrs = {android.R.attr.actionBarSize};
        TypedArray values = mContext.getTheme().obtainStyledAttributes(attrs);
        try {
            return values.getDimensionPixelSize(0, 0);//第一个参数数组索引,第二个参数 默认值
        } finally {
            values.recycle();
        }
    }

    public int getScreenWidth(Context mContext) {
        DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
        return dm.widthPixels;
    }}

AnimHelper.java

package lib.view.touxiang;

import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.view.View;
import android.view.animation.AccelerateInterpolator;

public class AnimHelper {

    private AnimHelper() {
        throw new RuntimeException("AnimHelper cannot be initialized!");
    }


    public static void zoomOut(View view) {
        ObjectAnimator alpha = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f);
        ObjectAnimator scaleX = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0f);
        ObjectAnimator scaleY = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0f);
        AnimatorSet set = new AnimatorSet();
        set.playTogether(alpha, scaleX, scaleY);
        set.setDuration(300);
        set.setInterpolator(new AccelerateInterpolator());
        set.start();
    }

    public static void zoomIn(View view) {
        ObjectAnimator alpha = ObjectAnimator.ofFloat(view, "alpha", 0f, 1f);
        ObjectAnimator scaleX = ObjectAnimator.ofFloat(view, "scaleX", 0f, 1f);
        ObjectAnimator scaleY = ObjectAnimator.ofFloat(view, "scaleY", 0f, 1f);
        AnimatorSet set = new AnimatorSet();
        set.playTogether(alpha, scaleX, scaleY);
        set.setDuration(300);
        set.setInterpolator(new AccelerateInterpolator());
        set.start();
    }

    public static void setViewX(View view, float originalX, float finalX, float percent) {
        float calcX = (finalX - originalX) * percent + originalX;
        view.setX(calcX);
    }

    public static void setViewY(View view, float originalY, float finalY, float percent) {
        float calcY = (finalY - originalY) * percent + originalY;
        view.setY(calcY);
    }

    public static void scaleView(View view, float originalSize, float finalSize, float percent) {
        float calcSize = (finalSize - originalSize) * percent + originalSize;
        float caleScale = calcSize / originalSize;
//        view.setScaleType(ImageView.ScaleType.CENTER);
        view.setScaleX(caleScale);
        view.setScaleY(caleScale);
    }
}

这样就完成了

至于左上角github上有很多例子。这是往正中间位移。

© 著作权归作者所有

共有 人打赏支持
lsy999
粉丝 0
博文 80
码字总数 24514
作品 0
程序员
Android 用什么动画会出现图片会缩小,然后露出下面的标题栏

Android 用什么动画会出现图片会缩小,然后露出下面的标题栏。

summer921025
2015/03/30
64
1
5- OpenCV+TensorFlow 入门人工智能图像处理-图片的几何变换(一)

图片的几何变换 图片的几何变换章节介绍 图片位移 & 图片缩放 图片剪切 & 图片镜像 图片仿射变换 Hog + Svm 小狮子识别 计算机视觉的基础: 裁剪样本为64,128 等比例缩放 仿射变换: 位移,旋转...

天涯明月笙
04/19
0
0
web实战:video结合canvas实现视频在线截图

给大家讲解下我前几天看到的一个有趣小demo:视频在线截图。以下是我修改和添加了新功能后的效果图: 是不是很酷,其实挺简单的,下面就给大家讲讲怎么弄哈。 这里主要分为三大块功能,首先是...

newbeehh
06/22
0
0
Qt之实现360安全卫士主界面(一)

该博文只是模仿360安全卫士的主界面,并不牵涉其中的任何业务功能;重在个人见解以及界面实现;关于360安全卫士的主界面,我想大家都见到过,毕竟基本大部分人都安装过这个软件,基于我对其界...

长平狐
2012/11/06
1K
1
cocos2d游戏地图的放大、缩小、移动

http://www.cnblogs.com/dingwenjie/archive/2012/03/28/2419805.html cocos2d游戏地图的放大、缩小、移动 在我刚学习cocos2d的时候,我是通过子龙山人的blog: http://www.cnblogs.com/andy...

晨曦之光
2012/05/28
1K
0
一起撸个微信图片浏览的BaseActivity吧(上)——初步思考与基础结构

本项目git: https://github.com/razerdp/ZoomViewActivity 【下篇】一起撸个微信图片浏览的BaseActivity吧(下)——过渡动画的实现 项目预览图: 距离上次更新博客有两三个月了。。。。太懒...

01/08
0
0
CSS3 3D Transform

前2011年5月就在站上写了一篇《CSS3 Transform》介绍CSS3中Transform属性的简单应用。但这篇文章里的知识无法满足大家对Transform的一个全面认识,最近重新整理了一个Transform系列的文章,希...

石佛慈悲
2013/12/16
0
0
用最短的CSS样式,勾勒大数据演示屏

先看案例效果,再看心得与总结 前段时间撸了一个演示平台,输入任一手机号,可追踪其行迹,类似《人民的名义》追踪丁义珍的效果,很明显涉密了,因此特意克隆了一个,并把后端阉割了,目前查...

maodayeyeye
06/11
0
0
理解欧拉公式,其实也没那么难。

最近看了3brown1blue的视频,通过集合论的方式来理解欧拉公式。 传送门:翻墙观看 欧拉公式的一种形式: 欧拉公式的难点是理解乘方是复数的意义,它并不是和1+1=2一样让人觉得理所应当,而是...

Stansosleepy
2017/05/01
0
0
arcgis api for js入门开发系列二十一 用HTML5 canvas绘制地图 瓦片加载平移缩放

终于开始可以写代码了,手都开始痒了。这里的代码仅仅是在chrome检测过,我可以肯定的是IE10以下浏览器是行不通,我一直在考虑,是不是使用IE禁止看我的篇博客,就是这群使用IE的人,给我加了...

sinat_34719507
2017/03/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

中国开始生产自主设计x86 CPU,由AMD授权

7 月 10 日报道,美媒称,中国正试图摆脱对美国公司的依赖并开发自己的芯片。据报道,中国制造商天津海光先进技术投资有限公司开始生产中国自主设计的“禅定”x86 中央处理器(CPU)。 7 月 ...

六库科技
1分钟前
0
0
Vue.js-自定义事件例子

自定义组件的 v-model 2.2.0+ 新增 一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value 特性用于不同的目的。m...

tianyawhl
1分钟前
0
0
mybatis中获取sqlSession的源码分析

0 SqlSessionFactoryBuilder类 SqlSessionFactoryBuilder sqlSessionFacotory=SqlSessionFactoryBuilder().build(reader) public SqlSessionFactory build(Reader reader) { return build(re......

writeademo
2分钟前
0
0
RobotThread.cpp

#include "RobotThread.h"RobotThread::RobotThread(int argc, char** pArgv, const char * topic) :m_Init_argc(argc), m_pInit_argv(pArgv), m_topic(topic){/** ......

itfanr
4分钟前
0
0
防御ddos攻击的常见方法

DDoS攻击是一种特殊形式的拒绝服务攻击。它利用多台已经被攻击者所控制的机器对某一台单机发起攻击,在带宽相对的情况下,被攻击的主机很容易失去反应能力。分布式拒绝服务攻击(DDoS) 是一种...

上树的熊
4分钟前
0
0
Vue全家桶问题合集(很多eslint规范问题)

自己使用Vue全家桶问题合集(很多eslint规范问题) 遇到很多问题一一道来。 1.vue报错 Do not use built-in or reserved HTML elements as component id:header 组件,不能和html标签重复 he...

kisshua
6分钟前
0
0
Spring框架中的设计模式(四)​

Spring框架中的设计模式(四) 本文是Spring框架中使用的设计模式第四篇。本文将在此呈现出新的3种模式。一开始,我们会讨论2种结构模式:适配器和装饰器。在第三部分和最后一部分,我们将讨...

瑞查德-Jack
11分钟前
0
0
如何玩转小程序+公众号?手把手教你JeeWx小程序CMS与公众号关联

随着微信小程序新功能、新入口的不断更新,小程序的商业价值逐步增强,特别是小程序与公众号的深度融合,已经让小程序成为各行业新的营销渠道。Jeewx平台专注小程序的开发,逐步完善小程序生...

Jeecg
17分钟前
0
0
IDEA开发vue.js卡顿

由于新项目使用了vue.js。在执行cnpm install后会在node_modules这个文件下面生成vue的相关依赖文件,这个时候当执行npm run dev命令时,会导致IDEA出现卡死的问题。 解决办法:在idea中设置...

落雪飞声
19分钟前
0
0
js模块化编程之彻底弄懂CommonJS和AMD/CMD!

先回答我:为什么模块很重要? 答:因为有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块。 但是,这样做有一个前提,那就是大家必须以同样的方式编写模块,否则你...

娇娇jojojo
19分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部