Android共享元素过渡动画
在本教程中,我们将实现另一种动画过渡,即活动之间的共享元素过渡。
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);
}
}

