Android共享元素过渡动画

时间:2020-02-23 14:29:16  来源:igfitidea点击:

在本教程中,我们将实现另一种动画过渡,即活动之间的共享元素过渡。

Android共享元素过渡动画

Android共享元素过渡确定在场景过渡期间如何将共享元素视图从一个活动/片段动画化为另一个活动/片段。

在棒棒糖之前的设备中,Android曾经用于支持活动和涉及整个视图层次结构过渡的片段之间的过渡。
但是,在很多情况下,视图(例如ListView)由不同的行项目组成。
通常,单击任何行都会在下一个屏幕中显示相应行的详细信息。
因此,为了强调这两个活动之间的连续性,我们将展示一个圆形的揭示动画。
通过将注意力集中在新屏幕和先前屏幕之间的关系上,可以改善用户体验。
像这样的共享元素转换在音乐播放列表应用中更为常见。

注意:这种类型的转换仅适用于android SDK> 21。

让我们开始实施该应用。
在本教程中,我们将实现自定义ListView行,并为每个行显示所需的过渡。

Android共享元素过渡动画项目结构

该项目包括2个活动和一个ListView的CustomAdapter。

Android Transition Animation –共享元素过渡代码

要启用此转换,请在" styles.xml"中的AppTheme标记内添加以下代码段。

<item name="android:windowContentTransitions">true</item>

对于这两个具有此过渡的布局,我们需要分配一个android:transitionName属性。

activity_main.xml填充一个ListView,而details_activity.xml用于详细信息屏幕。
两者都显示如下。

<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:transitionName="@string/transition"
  android:orientation="vertical">

 <ListView
     android:layout_width="wrap_content"
     android:id="@+id/list_view"
     android:layout_height="wrap_content"

</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
  xmlns:android="https://schemas.android.com/apk/res/android"
  xmlns:tools="https://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:padding="@dimen/activity_horizontal_margin"
  android:id="@+id/layout"
  android:transitionName="@string/transition"
  tools:context="com.theitroad.sharedelementtransition.MainActivity">

  <TextView
      android:gravity="center"
      android:textColor="@android:color/white"
      android:id="@+id/heading"
      android:layout_width="match_parent"
      android:textAppearance="?android:attr/textAppearanceLarge"
      android:layout_height="wrap_content" 

  <TextView
      android:gravity="center"
      android:id="@+id/language"
      android:textColor="@android:color/white"
      android:layout_width="match_parent"
      android:textAppearance="?android:attr/textAppearanceMedium"
      android:layout_height="wrap_content"
      android:layout_below="@+id/heading"
      android:layout_alignParentLeft="true"
      android:layout_alignParentStart="true" 

  <TextView
      android:gravity="center"
      android:id="@+id/desc"
      android:textColor="@android:color/white"
      android:layout_width="match_parent"
      android:textAppearance="?android:attr/textAppearanceMedium"
      android:layout_height="wrap_content"
      android:layout_centerInParent="true"
       

</RelativeLayout>

如您所见,在两个布局的根视图中,ʻandroid:transitionName`属性均声明为字符串。

我们创建了一个自定义ListView,它从String数组的ArrayList填充其布局。
ListView的布局和适配器如下。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
  android:orientation="vertical" android:layout_width="match_parent"
  android:padding="@dimen/activity_horizontal_margin"
  android:background="@color/md_black_1000"
  android:layout_margin="5dp"
  android:id="@+id/rl"
  android:layout_height="wrap_content">

  <TextView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:textAppearance="?android:attr/textAppearanceLarge"
      android:id="@+id/primary_textview"
      android:gravity="center"
      android:textColor="@android:color/white"
       

  <TextView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:textAppearance="?android:attr/textAppearanceMedium"
      android:id="@+id/textView"
      android:layout_below="@+id/primary_textview"
      android:textColor="@android:color/white"
      android:gravity="center"
       

</RelativeLayout>
public class CustomAdapter extends BaseAdapter {
  ArrayList<String[]> arrayList;
  Context c;

  public CustomAdapter(Context c, ArrayList<String[]> list) {
      arrayList = list;
      this.c = c;

  }

  @Override
  public int getCount() {
      //TODO Auto-generated method stub
      return arrayList.size();
  }

  @Override
  public Object getItem(int position) {
      //TODO Auto-generated method stub
      return arrayList.get(position);
  }

  @Override
  public long getItemId(int position) {
      //TODO Auto-generated method stub
      return position;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
      //TODO Auto-generated method stub
      View row = null;
      LayoutInflater inflater = (LayoutInflater) c
              .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      if (convertView == null) {
          row = inflater.inflate(R.layout.row_layout, parent,
                  false);
      } else {
          row = convertView;
      }
      String[] detail = arrayList.get(position);

      RelativeLayout rl= (RelativeLayout)row.findViewById(R.id.rl);
      rl.setBackgroundColor(Color.parseColor(detail[3]));
      TextView name = (TextView) row.findViewById(R.id.primary_textview);
      name.setText(detail[0]);
      TextView email = (TextView) row.findViewById(R.id.textView);
      email.setText(detail[1]);

      return row;
  }

}

MainActivity.java和DetailsActivity.java在下面给出。

package com.theitroad.sharedelementtransition;

import android.content.Intent;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      final ArrayList<String[]> values = new ArrayList<String[]>();
      values.add(new String[]{"Android", "Java", getString(R.string.android),'#' + Integer.toHexString(getResources().getColor(R.color.md_light_green_900))});
      values.add(new String[]{"iOS", "Swift", getString(R.string.ios),'#' + Integer.toHexString(getResources().getColor(R.color.md_amber_A700))});
      values.add(new String[]{"Xamarin", "C#",getString(R.string.xamarin),'#' + Integer.toHexString(getResources().getColor(R.color.md_pink_A700))});
      values.add(new String[]{"PhoneGap", "HTML CSS and JScript",getString(R.string.phonegap),'#' + Integer.toHexString(getResources().getColor(R.color.md_brown_800))});

      ListView listView = (ListView) findViewById(R.id.list_view);
      CustomAdapter adapter = new CustomAdapter(this, values);
      listView.setAdapter(adapter);

      listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
          @Override
          public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

              Intent intent = new Intent(MainActivity.this, DetailsActivity.class);
              intent.putExtra("array",values.get(position));
              //Get the transition name from the string
              String transitionName = getString(R.string.transition);

              ActivityOptionsCompat options =

                      ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this,
                              view,   //Starting view
                              transitionName    //The String
                      );

              ActivityCompat.startActivity(MainActivity.this, intent, options.toBundle());
          }
      });
  }
}

活动结束后,我们将调用ʻActivityCompat.finishAfterTransition(this);而不是finish(),如下面的代码所示。

public class DetailsActivity extends AppCompatActivity {

  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.details_activity);

     String[] array= getIntent().getStringArrayExtra("array");

      RelativeLayout rl= (RelativeLayout)findViewById(R.id.layout);
      rl.setBackgroundColor(Color.parseColor(array[3]));

      TextView textView= (TextView)findViewById(R.id.heading);
      textView.setText(array[0]);
      TextView type= (TextView)findViewById(R.id.language);
      type.setText(array[1]);
      TextView desc=(TextView)findViewById(R.id.desc);
      desc.setText(array[2]);

  }

  @Override
  public void onBackPressed() {
      ActivityCompat.finishAfterTransition(this);
  }
}