私が欲しいのは、ユーザーがListViewのリスト項目をクリックすると、アクティビティ全体に変換されることです(次の例で見ることができます)が、これを説明するチュートリアルを見つけることができず、実際にはこの動きがどのように呼ばれているのか分からない。
言い換えれば、私が達成したいことは:
クリックするとリストアイテムの昇格が増加します(右のgifを参照)。
リスト項目を展開し、クリックされた項目に関する詳細情報を含む次のフラグメント/アクティビティレイアウトに変換します
私は多くの移行を試みましたが、運はありませんでした。誰でもこれを達成するのを手伝ってくれますか?
目的の効果を伴う2つのアクティビティ間を遷移する小さなサンプルアプリケーションを作成します。
ただし、提供されるgifのトランジションはわずかに異なります。左側のgifのトランジションは、リスト要素を2番目のアクティビティのコンテンツ領域にトランジションします(ツールバーはそのままです)。右側のgifで、遷移はリスト要素を2番目のアクティビティの完全な画面に変換します。次のコードは、左のgifで効果を提供します。ただし、適切なgifの移行を実現するために、わずかな修正を加えてソリューションを適応させることは可能です。
これはLollipopでのみ機能することに注意してください。ただし、古いデバイスで異なる効果を模倣することは可能です。さらに、提供されたコードの唯一の目的は、それがどのように行われるかを示すことです。これをアプリで直接使用しないでください。
主な活動:
public class MainActivity extends AppCompatActivity {
MyAdapter myAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
ListView listView = (ListView) findViewById(R.id.list_view);
myAdapter = new MyAdapter(this, 0, DataSet.get());
listView.setAdapter(myAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, final View view, final int position, long id) {
startTransition(view, myAdapter.getItem(position));
}
});
}
private void startTransition(View view, Element element) {
Intent i = new Intent(MainActivity.this, DetailActivity.class);
i.putExtra("ITEM_ID", element.getId());
Pair<View, String>[] transitionPairs = new Pair[4];
transitionPairs[0] = Pair.create(findViewById(R.id.toolbar), "toolbar"); // Transition the Toolbar
transitionPairs[1] = Pair.create(view, "content_area"); // Transition the content_area (This will be the content area on the detail screen)
// We also want to transition the status and navigation bar barckground. Otherwise they will flicker
transitionPairs[2] = Pair.create(findViewById(Android.R.id.statusBarBackground), Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME);
transitionPairs[3] = Pair.create(findViewById(Android.R.id.navigationBarBackground), Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME);
Bundle b = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this, transitionPairs).toBundle();
ActivityCompat.startActivity(MainActivity.this, i, b);
}
}
activity_main.xml:
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical">
<Android.support.v7.widget.Toolbar
Android:id="@+id/toolbar"
Android:layout_width="match_parent"
Android:layout_height="?attr/actionBarSize"
Android:background="@color/colorPrimary"
Android:transitionName="toolbar" />
<ListView
Android:id="@+id/list_view"
Android:layout_width="match_parent"
Android:layout_height="match_parent" />
</LinearLayout>
DetailActivity:
public class DetailActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
long elementId = getIntent().getLongExtra("ITEM_ID", -1);
Element element = DataSet.find(elementId);
((TextView) findViewById(R.id.title)).setText(element.getTitle());
((TextView) findViewById(R.id.description)).setText(element.getDescription());
// if we transition the status and navigation bar we have to wait till everything is available
TransitionHelper.fixSharedElementTransitionForStatusAndNavigationBar(this);
// set a custom shared element enter transition
TransitionHelper.setSharedElementEnterTransition(this, R.transition.detail_activity_shared_element_enter_transition);
}
}
activity_detail.xml:
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical">
<Android.support.v7.widget.Toolbar
Android:id="@+id/toolbar"
Android:layout_width="match_parent"
Android:layout_height="?attr/actionBarSize"
Android:background="@color/colorPrimary"
Android:transitionName="toolbar" />
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:background="#abc"
Android:orientation="vertical"
Android:paddingBottom="200dp"
Android:transitionName="content_area"
Android:elevation="10dp">
<TextView
Android:id="@+id/title"
Android:layout_width="match_parent"
Android:layout_height="wrap_content" />
<TextView
Android:id="@+id/description"
Android:layout_width="match_parent"
Android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
detail_activity_shared_element_enter_transition.xml(/ res/transition /):
<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:transitionOrdering="together">
<changeBounds/>
<changeTransform/>
<changeClipBounds/>
<changeImageTransform/>
<transition class="my.application.transitions.ElevationTransition"/>
</transitionSet>
my.application.transitions.ElevationTransition:
@TargetApi(Build.VERSION_CODES.Lollipop)
public class ElevationTransition extends Transition {
private static final String PROPNAME_ELEVATION = "my.elevation:transition:elevation";
public ElevationTransition() {
}
public ElevationTransition(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void captureStartValues(TransitionValues transitionValues) {
captureValues(transitionValues);
}
@Override
public void captureEndValues(TransitionValues transitionValues) {
captureValues(transitionValues);
}
private void captureValues(TransitionValues transitionValues) {
Float elevation = transitionValues.view.getElevation();
transitionValues.values.put(PROPNAME_ELEVATION, elevation);
}
@Override
public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, TransitionValues endValues) {
if (startValues == null || endValues == null) {
return null;
}
Float startVal = (Float) startValues.values.get(PROPNAME_ELEVATION);
Float endVal = (Float) endValues.values.get(PROPNAME_ELEVATION);
if (startVal == null || endVal == null || startVal.floatValue() == endVal.floatValue()) {
return null;
}
final View view = endValues.view;
ValueAnimator a = ValueAnimator.ofFloat(startVal, endVal);
a.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
view.setElevation((float)animation.getAnimatedValue());
}
});
return a;
}
}
TransitionHelper:
public class TransitionHelper {
public static void fixSharedElementTransitionForStatusAndNavigationBar(final Activity activity) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Lollipop)
return;
final View decor = activity.getWindow().getDecorView();
if (decor == null)
return;
activity.postponeEnterTransition();
decor.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@TargetApi(Build.VERSION_CODES.Lollipop)
@Override
public boolean onPreDraw() {
decor.getViewTreeObserver().removeOnPreDrawListener(this);
activity.startPostponedEnterTransition();
return true;
}
});
}
public static void setSharedElementEnterTransition(final Activity activity, int transition) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Lollipop)
return;
activity.getWindow().setSharedElementEnterTransition(TransitionInflater.from(activity).inflateTransition(transition));
}
}
それでは、ここで異なる部分は何ですか:2つのアクティビティがあります。移行中に、アクティビティ間で4つのビューが移行されます。
ツールバー:左のgifのように、ツールバーは他のコンテンツとともに移動しません。
ListView要素View->は、DetailActivityのコンテンツビューになります
ステータスバーとナビゲーションバーの背景:これらのビューを遷移ビューのセットに追加しない場合、遷移中にフェードアウトします。ただし、これにはEnter遷移の遅延が必要です(TransitionHelper.fixSharedElementTransitionForStatusAndNavigationBar
)
MainActivity
では、DetailActivity
を開始するために使用されるバンドルに遷移ビューが追加されます。さらに、両方のアクティビティで、遷移したビューに名前を付ける必要があります(transitionName
)。これは、プログラムだけでなくレイアウトxmlでも実行できます。
共有要素の遷移中に使用される遷移のデフォルトセットは、ビューのさまざまな側面に影響します(たとえば、ビューの境界- 2 を参照)。ただし、ビューの標高の違いはアニメーション化されません。これが、提示されたソリューションがカスタムのElevationTransitionを使用する理由です。
これを試してください。 Material-Animations
blueIconImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(MainActivity.this, SharedElementActivity.class);
View sharedView = blueIconImageView;
String transitionName = getString(R.string.blue_name);
ActivityOptions transitionActivityOptions = ActivityOptions.makeSceneTransitionAnimation(MainActivity.this, sharedView, transitionName);
startActivity(i, transitionActivityOptions.toBundle());
}
});
この壮大なウェブページをお試しください@ アクティビティとフラグメントの移行の開始(パート1) 。ここで、彼らはアクティビティとフラグメントの移行について話しました。試したことがありません。私の見解では、Fragment Transitionsはより優れており、コンピューターへの負荷が少ないので、良いスタートです。また、ツールバーを変更する必要はないかもしれません。ツールバーを表示/非表示できます。
別の良いSOリンクは@ フラグメント間の遷移をアニメーション化する 、ベストアンサーを見てください。その投稿で、彼らは objectAnimator。
別の意見としては、投稿したサンプルアニメーションに関するもので、ある芸術から別の芸術へのスムーズなアニメーションは表示されません。アニメーションが滑らかでない場合は、それほど印象的ではありません。
頑張って、楽しんで、みんなに投稿してください。