需要實現的的效果
描述:一開始是完全顯示的,然後高度慢慢減少,圖片自上而下消失。
分析:這個效果看似很簡單,但是實際上根據常規的android機制,是很難以實現的。
常規方案
- Imageview變化大小,只會整體壓縮,不可行
- 外佈局一個RelativeLayout,Imageview靠底部對齊,然後自上而下減少外佈局高度,也會壓縮圖像,還是不可行
- 用一個空白的佈局慢慢遮擋圖片,實現了現在的效果,但是時間佔用了額外的空間。圖像消失的部分是有內容需要顯示的。不符合要求。
解決方案
想了很久,突然聯想到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));