1. 程式人生 > 程式設計 >Android屬性動畫實現圖片從左到右逐漸消失

Android屬性動畫實現圖片從左到右逐漸消失

前言:dp/dip代表獨立畫素,dpi代表螢幕每英寸畫素點的個數,px與dp的轉換公式為: px = dp *(dpi / 160)

一、效果圖

二、原始碼

AnimationActivity:

package com.example.duoyi.clientaidl;
 
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.CardView;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
 
import com.example.duoyi.AnimationAdapter;
 
import java.util.ArrayList;
import java.util.List;
 
public class AnimationActivity extends AppCompatActivity {
 
 private static final int MAX_COUNT = 100;
 private static final String TAG = "AnimationActivity";
 
 RecyclerView rv;
 CardView cv;
 ImageView image;
 ObjectAnimator animator;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_animation);
 
  rv = findViewById(R.id.itemRv);
  cv = findViewById(R.id.expand);
  image = findViewById(R.id.insect);
 
  List<String> list = new ArrayList<>();
  for (int i = 0; i < MAX_COUNT; i++) {
   list.add("世界很美好,隊形走起" + i);
  }
 
  LinearLayoutManager manager = new LinearLayoutManager(this);
  manager.setOrientation(RecyclerView.VERTICAL);
  AnimationAdapter adapter = new AnimationAdapter(list,this);
  rv.setLayoutManager(manager);
  rv.setAdapter(adapter);
  rv.scrollToPosition(list.size() - 1);
 
  image.setTranslationX(dp2px(50));
 
  //監聽recyclerview的滑動事件
  rv.addOnScrollListener(new RecyclerView.OnScrollListener() {
   @Override
   public void onScrollStateChanged(RecyclerView recyclerView,int newState) {
    super.onScrollStateChanged(recyclerView,newState);
    Log.i(TAG,"current scroll state = " + newState);
    image.setTranslationX(dp2px(-1));
    if (newState == RecyclerView.SCROLL_STATE_IDLE) {
     //第一種動畫方式
//     image.animate()
//       .translationX(dp2px(50))
//       .setDuration(1500)
//       .start();
     //第二種動畫方式
     animator = ObjectAnimator.ofFloat(image,"translationX",dp2px(50));
     animator.setDuration(1500);
     animator.addListener(new Animator.AnimatorListener() {
      @Override
      public void onAnimationStart(Animator animation) {
 
      }
 
      @Override
      public void onAnimationEnd(Animator animation) {
       //當圖片發生點選時可以通過下面程式碼將圖片復位到原來位置
       //否則響應點選事件的圖片可能會顯示不全,不響應點選的忽略
       //image.setTranslationX(dp2px(-1));
      }
 
      @Override
      public void onAnimationCancel(Animator animation) {
 
      }
 
      @Override
      public void onAnimationRepeat(Animator animation) {
 
      }
     });
     animator.start();
    }
   }
  });
 
  image.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    if (animator != null && animator.isRunning()) {
     animator.cancel();
    }
    image.setImageResource(R.drawable.insect);
   }
  });
 }
 
 public int dp2px(int dip) {
  int dpi = getResources().getDisplayMetrics().densityDpi;
  return dip * (dpi / 160);
 }
}

activity_animator.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 tools:context=".AnimationActivity">
 
 <android.support.v7.widget.RecyclerView
  android:id="@+id/itemRv"
  android:layout_width="match_parent"
  android:layout_height="match_parent" />
 
 <android.support.v7.widget.CardView
  android:id="@+id/expand"
  android:layout_width="70dp"
  android:layout_height="30dp"
  android:layout_alignParentEnd="true"
  android:layout_marginTop="40dp"
  android:layout_marginEnd="30dp"
  app:cardBackgroundColor="#00000000"
  app:cardCornerRadius="15dp"
  app:cardElevation="0dp">
 
  <ImageView
   android:id="@+id/insect"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:layout_gravity="end"
   android:scaleType="fitXY"
   android:src="@drawable/insect" />
 
 </android.support.v7.widget.CardView>
 
 
</RelativeLayout>

item_anim.xml:

<?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="50dp"
 tools:context=".AnimationActivity">
 
 <TextView
  android:textSize="16sp"
  android:id="@+id/content"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_centerInParent="true"
  android:text="hello World" />
 
 
</RelativeLayout>

AnimatorAdapter.java:

package com.example.duoyi;
 
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
 
import com.example.duoyi.clientaidl.AnimationActivity;
import com.example.duoyi.clientaidl.R;
 
import java.util.List;
 
public class AnimationAdapter extends RecyclerView.Adapter<AnimationAdapter.AnimationViewHolder> {
 
 private List<String> list;
 private AnimationActivity context;
 
 public AnimationAdapter(List<String> list,AnimationActivity context) {
  this.list = list;
  this.context = context;
 }
 
 @Override
 public AnimationViewHolder onCreateViewHolder(ViewGroup viewGroup,int i) {
  View view = LayoutInflater.from(context).inflate(R.layout.item_anim,viewGroup,false);
  return new AnimationViewHolder(view);
 }
 
 @Override
 public void onBindViewHolder(AnimationViewHolder holder,int position) {
  String content = list.get(position);
  holder.content.setText(content);
 }
 
 @Override
 public int getItemCount() {
  return list.size();
 }
 
 static class AnimationViewHolder extends RecyclerView.ViewHolder {
 
  TextView content;
 
  AnimationViewHolder(View view) {
   super(view);
   content = view.findViewById(R.id.content);
  }
 }
}

三、邏輯分析

首先實現的效果是圖片從做到右顯示,那我們就使用平移動畫,讓圖片從左到右移動消失,所以就在需要顯示ImageView巢狀一層父容器,這樣圖片不斷移出容器的範圍內就會造成一種圖片從左到右消失的效果

需求:父容器需設定為圓角顯示

如果需要實現ImageView的父容器為圓角佈局的話,那就採用CardView,通過改變其屬性

app:cardCornerRadius="15dp"

實現,不要使用其他諸如LinearLayout的父容器,設定其backgroud為一個圓角的drawable方式實現,這樣的話內部的圖片如果是矩形,即時你設定了父容器為圓角的,但是內部圖片的顯示還是會超出圓角的範圍顯示

需求:圖片消失的動畫中響應點選事件,完整顯示另一張圖片

這個實現我們首先需要在圖片的點選事件中判斷當前動畫是否還是執行isRunning(),如果執行的話呼叫animator的cancel()方法取消動畫,然後進行圖片的位置的復位;如果我們不進行復位操作,此時ImageView的位置由於平移動畫發生改變,當我們顯示另一張圖片可能會發生顯示不全情況

當動畫終止(可能自然終止,也可能呼叫了動畫的cance()方法),會響應其結束的監聽方法,然後我們在該方法復位圖片的位置即可:

animator.addListener(new Animator.AnimatorListener() {
      @Override
      public void onAnimationStart(Animator animation) {
      }
      @Override
      public void onAnimationEnd(Animator animation) {
       //當圖片發生點選時可以通過下面程式碼將圖片復位到原來位置
       //否則響應點選事件的圖片可能會顯示不全,不響應點選的忽略
       //image.setTranslationX(dp2px(-1));
      }
      @Override
      public void onAnimationCancel(Animator animation) {
      }
      @Override
      public void onAnimationRepeat(Animator animation) {
      }
     });

動畫實現的兩種方式:

直接通過元件的animator()方式可以實現動畫的鏈式呼叫,並且可以通過其withEndAction()或者withStartAction()方法在動畫啟動和結束的時候執行一些邏輯,該方式可以不需要呼叫其start()就能執行,因為其會在螢幕重新整理的時候會自動執行

//第一種動畫方式
image.animate()
  .translationX(dp2px(50))
  .setDuration(1500)
  .start();

下面這種方式就是比較老實的方式,但是我們可以通過將其賦值給一個全域性變數進行動畫的操控(pause() cancel())

animator = ObjectAnimator.ofFloat(image,dp2px(50));
animator.setDuration(1500);
animato.start();

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。