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); } }