Intereting Posts
Синхронизировать данные SQLite с телефона Android на Windows PC База данных MySql Элемент становится больше при сдвиге ListView Запуск нескольких кнопок (событие onClick) одним нажатием / жестом Android Listview с помощью Google maps Как предотвратить входящие SMS-сообщения от входящих сообщений? Binding onScrolling прослушиватель android ListView Длинный клик по кликируемому диапазону не срабатывает, пока не появится щелчок Можете ли вы установить цвет фона на кнопке переключения, не закрывая переключатель? Android M onRequestPermissionsResult в неактивности Всплывающее меню выходит из экрана Как сделать скриншоты эмулятора с помощью Eclipse? Android WebView показывает пустую страницу Google Play Services делает apk слишком большим Почему элементы исчезают, когда я просматриваю listView? Есть ли способ создать службу фонового процесса, которая будет запускаться независимо от того, создано ли приложение, оно еще работает?

Android – Как создать переход от элемента в списке к целому действию?

Я хочу, чтобы, когда пользователь щелкает элемент списка в ListView, он преобразуется в целую активность (как вы можете видеть в следующем примере), но я не смог найти учебник, объясняющий это, и, фактически, я делаю Не знаю, как это движение называется.

Другими словами, я хочу достичь:

  1. Увеличение высоты элемента списка при нажатии (как вы можете видеть в правом gif)

  2. Разверните и преобразуйте элемент списка в следующий макет фрагмента / действия, содержащий подробную информацию о клике

Введите описание изображения здесь Введите описание изображения здесь

Я пробовал много переходов, но не повезло. Может ли кто-нибудь помочь мне выполнить это?

Я создаю небольшое примерное приложение, которое переходит между двумя действиями с желаемым эффектом: Пример приложения

Однако переходы в предоставленных gifs несколько отличаются. Переход в gif с левой стороны переводит элемент списка в область содержимого второго действия (панель инструментов остается на месте). В gif с правой стороны переход преобразует элемент списка в полный экран второго действия. Следующий код обеспечивает эффект в левом 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)); } } 

Итак, какие здесь разные части: у нас есть два вида деятельности. Во время перехода между видами деятельности переходят четыре вида.

  • Панель инструментов: как и в левой панели, панель инструментов не перемещается вместе с остальной частью содержимого.

  • Элемент ListView View -> становится представлением содержимого DetailActivity

  • StatusBar и NavigationBar Background: если мы не добавим эти представления к набору пересмотренных представлений, они будут исчезать и вернуться во время перехода. Однако это требует задержки перехода ввода (см. TransitionHelper.fixSharedElementTransitionForStatusAndNavigationBar )

В MainActivity переходные представления добавляются в Bundle, который используется для запуска функции 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()); } }); 

SharedElements

Анимация, которая вам нужна, называется Activity Transitions между общими элементами. По исследованиям я обнаружил, что вам следует:

  1. Поместите представление ListView в relativeLayout
  2. OnClick, раздуйте копию своего рендеринга
  3. Найти глобальные координаты, в которых средство визуализации находится во взаимодействии с родительским элементом ListView
  4. Добавьте скопированный рендеринг в RelativeLayout (родительский элемент ListView)
  5. Анимируйте списокView away
  6. В конце этого оживить, оживить ваш новый рендерер
  7. Прибыль!

      public class MainActivity extends Activity { private RelativeLayout layout; private ListView listView; private MyRenderer selectedRenderer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); layout = new RelativeLayout(this); setContentView(layout); listView = new ListView(this); RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); layout.addView(listView, rlp); listView.setAdapter(new MyAdapter()); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // find out where the clicked view sits in relationship to the // parent container int t = view.getTop() + listView.getTop(); int l = view.getLeft() + listView.getLeft(); // create a copy of the listview and add it to the parent // container // at the same location it was in the listview selectedRenderer = new MyRenderer(view.getContext()); RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(view.getWidth(), view .getHeight()); rlp.topMargin = t; rlp.leftMargin = l; selectedRenderer.textView.setText(((MyRenderer) view).textView.getText()); layout.addView(selectedRenderer, rlp); view.setVisibility(View.INVISIBLE); // animate out the listView Animation outAni = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, -1f, Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f); outAni.setDuration(1000); outAni.setFillAfter(true); outAni.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { ScaleAnimation scaleAni = new ScaleAnimation(1f, 1f, 1f, 2f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); scaleAni.setDuration(400); scaleAni.setFillAfter(true); selectedRenderer.startAnimation(scaleAni); } }); listView.startAnimation(outAni); } }); } public class MyAdapter extends BaseAdapter { @Override public int getCount() { return 10; } @Override public String getItem(int position) { return "Hello World " + position; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { MyRenderer renderer; if (convertView != null) renderer = (MyRenderer) convertView; else renderer = new MyRenderer(MainActivity.this); renderer.textView.setText(getItem(position)); return renderer; } } public class MyRenderer extends RelativeLayout { public TextView textView; public MyRenderer(Context context) { super(context); setPadding(20, 20, 20, 20); setBackgroundColor(0xFFFF0000); RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); rlp.addRule(CENTER_IN_PARENT); textView = new TextView(context); addView(textView, rlp); } } } 

Попробуйте эту захватывающую веб-страницу @ Начало работы с действиями и переходы фрагментов (часть 1) . Здесь они рассказывали об активности и переходах фрагментов. Я не пробовал. Я считаю, что Fragment Transitions лучше и менее интенсивно работает в компьютере, поэтому это хороший старт. И вам, возможно, не придется менять панели инструментов, вы можете отображать / скрывать их.

Другая хорошая ссылка SO – это @ Анимация перехода между фрагментами , посмотрите на лучший ответ. В этом сообщении они говорили об объекте Animator .

Другое мнение о том, как вы разместили образец анимации, не показывает гладкую анимацию от одного искусства к другому. Это менее впечатляет, когда анимация негладкая.

Удачи, получайте удовольствие, держите нас всех в курсе.