android實現圖片向上展開和慢慢摺疊的過度動畫

需要實現的的效果

描述:一開始是完全顯示的,然後高度慢慢減少,圖片自上而下消失。

分析:這個效果看似很簡單,但是實際上根據常規的android機制,是很難以實現的。

常規方案

  1. Imageview變化大小,只會整體壓縮,不可行
  2. 外佈局一個RelativeLayout,Imageview靠底部對齊,然後自上而下減少外佈局高度,也會壓縮圖像,還是不可行
  3. 用一個空白的佈局慢慢遮擋圖片,實現了現在的效果,但是時間佔用了額外的空間。圖像消失的部分是有內容需要顯示的。不符合要求。

解決方案

想了很久,突然聯想到MeasureSpec的三種情況(自適應,合父佈局一樣和絕對大小)。感覺圖像設置爲絕對大小並且靠底部對齊。然後自上而下減少外佈局高度,應該可以實現效果。

首先

自定義絕對大小的Imageview

package com.example.gbq.test.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.widget.ImageView;

import com.example.gbq.test.util.CommonUtil;

@SuppressLint("AppCompatCustomView")
public class AnimImageView extends ImageView {
    private static final int IMAGE_HEIGHT = 200;

    public AnimImageView(Context context) {
        super(context);
    }


    public AnimImageView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs, 0);
    }

    public AnimImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr, 0);

    }

    /**
     * 設置的高度最好是bitmap的高度,這樣不好壓縮變形。這裏寫死了
     * @param widthMeasureSpec 寬度
     * @param heightMeasureSpec 高度
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(widthMeasureSpec, CommonUtil.dip2px(IMAGE_HEIGHT));
    }
}

佈局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/bt_scale_big"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="60dp"
        android:text="@string/scale_big" />

    <Button
        android:id="@+id/bt_scale_small"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/bt_scale_big"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="30dp"
        android:text="@string/scale_small" />

    <RelativeLayout
        android:id="@+id/ll_content"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_alignParentBottom="true">

        <com.example.gbq.test.view.AnimImageView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_alignParentBottom="true"
            android:src="@mipmap/bg_anim_test" />
    </RelativeLayout>


</RelativeLayout>

動畫實現

package com.example.gbq.test;

import android.animation.ValueAnimator;
import android.os.Bundle;
import android.os.StrictMode;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.RelativeLayout;

import com.example.gbq.test.util.CommonUtil;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private RelativeLayout mContentLayout;
    private RelativeLayout.LayoutParams mLayoutParams;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (BuildConfig.DEBUG) {
            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll()
                    .penaltyLog().build());
            StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog()
                    .build());
        }
        findIds();
    }

    private void findIds() {
        mContentLayout = findViewById(R.id.ll_content);
        findViewById(R.id.bt_scale_big).setOnClickListener(this);
        findViewById(R.id.bt_scale_small).setOnClickListener(this);
        mLayoutParams = (RelativeLayout.LayoutParams)
                mContentLayout.getLayoutParams();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bt_scale_big:
                animScaleBig();
                break;
            case R.id.bt_scale_small:
                animScaleSmall();
                break;
            default:
                break;
        }
    }

    private void animScaleBig() {
        ValueAnimator scaleBig = ValueAnimator.ofFloat(100, 200);
        scaleBig.setInterpolator(new LinearInterpolator());
        scaleBig.setDuration(1000);
        scaleBig.addUpdateListener(mListener);
        scaleBig.start();
    }

    private ValueAnimator.AnimatorUpdateListener mListener = new ValueAnimator
            .AnimatorUpdateListener() {

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            mLayoutParams.height = CommonUtil.dip2px((float) animation.getAnimatedValue());
            mContentLayout.setLayoutParams(mLayoutParams);
        }
    };

    private void animScaleSmall() {
        ValueAnimator scaleBig = ValueAnimator.ofFloat(200, 100);
        scaleBig.setInterpolator(new LinearInterpolator());
        scaleBig.setDuration(1000);
        scaleBig.addUpdateListener(mListener);
        scaleBig.start();
    }
}

最終驗證方案是可行的。

總結:要多讀書,記住原理。再難得問題也是由基礎知識解決黨的。就像這個效果,看似簡單,細想很難很難。但是實現效果的關鍵不過就是一行代碼:

setMeasuredDimension(widthMeasureSpec, CommonUtil.dip2px(IMAGE_HEIGHT));
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章