Перейти к содержимому

Как сделать переход между activity в android studio

  • автор:

Как сделать переход между activity в android studio

В прошлых темах мы рассмотрели жизненный цикл activity и запуск новых activity с помощью объекта Intent. Теперь рассмотрим некоторые особенности взаимодействия между activity в одном приложении. Допустим, у нас есть три activity: MainActivity, SecondActivity и ThirdActivity.

Back stak и управление стеком из Activity в Android и Java

С помощью Intent, например, по нажатию кнопки MainActivity запускает SecondActivity:

Intent intent = new Intent(this, SecondActivity.class); startActivity(intent);

На SecondActivity тоже есть кнопка, которая запускает ThirdActivity:

Intent intent = new Intent(this, ThirdActivity.class); startActivity(intent);

На ThirdActivity также есть кнопка, которая возвращается к первой activity — MainActivity:

Intent intent = new Intent(this, MainActivity.class); startActivity(intent);

Взаимодействие между Activity в Android и Java

Если мы последовательно запустим все activity: из главной MainActivity запустим SecondActivity, из SecondActivity — ThirdActivity, то в итоге у нас сложится следующий стек activity:

ThirdActivity
SecondActivity
MainActivity

Если после этого из ThirdActivity мы захотим обратиться к MainActivity, то метод startActivity() запустит новый объект MainActivity (а не вернется к уже существующему), и стек уже будет выглядеть следующим образом:

MainActivity
ThirdActivity
SecondActivity
MainActivity

То есть у нас будут две независимые копии MainActivity. Такое положение нежелательно, если мы просто хотим перейти к существующей. И этот момент надо учитывать.

Если мы нажмем на кнопку Back (Назад) , то текущая activity, которая находится на вершине стека, удаляется из стека, и предыдущая activity оказывается на вершине стека и возобновляет свою работу. И таким образом с помощью кнопки Back (Назад) мы сможем перейти к предыдущей activity в стеке. Например, в случае выше если мы нажмем на кнопку Назад, то MainActivity на вершине стека завершает свою работу, и на экране начинает отображаться ThirdActivity

ThirdActivity
SecondActivity
MainActivity

Тем не менее иногда возникает необходимость упавлять переходом между activity. Например, в данном случае нам нежелательно при нажатии на кнопку в ThirdActivity запускать новую копию MainActivity вместо того, чтобы просто перейти к MainActivity, которая была запущена первой и находится в самом низу стека. Рассмотрим, какие возможности предоставляет нам Android.

Управление стеком activity

Для управления стеком из activity Android предлагает нам использовать флаги — константы, определенные в классе Intent . Применение определенного флага позволит нам определенным образом изменить положение в стеке для определенных activity.

Например, возьмем предыдущую задачу, когда после нажатия на кнопку в ThirdActivity запускается новый экземпляр MainActivity. Но мы хотим не запускать новую, а перейти к уже существующей.

MainActivity
ThirdActivity
SecondActivity
MainActivity

Чтобы выйти из этой ситуации, мы можем использовать флаг Intent.FLAG_ACTIVITY_REORDER_TO_FRONT :

Intent intent = new Intent(this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); startActivity(intent);

флаг Intent.FLAG_ACTIVITY_REORDER_TO_FRONT перемещает activity, к которой осуществляется переход на вершину стека, если она ужее есть в стеке. И в этом случае после перехода из ThirdActivity к MainActivity стек будет выглядеть следующим образом:

MainActivity
ThirdActivity
SecondActivity

Если же нам просто надо перейти из ThirdActivity к MainActivity, как если бы мы перешли назад с помощью кнопки Back, то мы можем использовать флаги Intent.FLAG_ACTIVITY_CLEAR_TOP и Intent.FLAG_ACTIVITY_SINGLE_TOP :

Intent intent = new Intent(this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); startActivity(intent);

Флаг Intent.FLAG_ACTIVITY_CLEAR_TOP очищает все activity кроме той, которая запускается (если она уже есть в стеке). А флаг Intent.FLAG_ACTIVITY_SINGLE_TOP указывает, что если в вершине стеке уже есть activity, которую надо запустить, то она НЕ запускается (то она может существовать в стеке только в единичном виде).

В этом случае после перехода из ThirdActivity к MainActivity стек будет полностью очищен, и там останется одна MainActivity.

Еще один флаг — Intent.FLAG_ACTIVITY_NO_HISTORY позволит не сохранять в стеке запускаемую activity. Например, при запуске SecondActivity мы не хотим ее сохранять в стеке:

Intent intent = new Intent(this, SecondActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); startActivity(intent);

В этом случае при переходе по цепочке MainActivity -> SecondActivity -> ThirdActivity стек будет выглядеть следующим образом:

MainActivity
ThirdActivity

#5 – Переход между страницами

#5 – Переход между страницами

Любое Андроид приложение может содержать множество страниц. Каждая страница представлена в виде Activity. За урок мы научимся переходить с одной активити в другую при помощи встроенного класса Intent.

Видеоурок

Андроид приложения могут состоять из множества страниц (Активити). Для выполнения перехода между страницами используется класс Intent.

Его реализация проста и она представлена чуть ниже:

// Создаем объект класса Intent intent = new Intent(this, SecondActivity.class); // Выполняем переход startActivity(intent);

Android Studio: Переключение между Activity

Рабочая среда Android Studio позволяет протестировать готовое приложение, для этого Вам необходимо создать виртуальное устройство. Для этого перейдите в AVD Manager.

Android Studio: Переключение между Activity

Назовём рабочую область BackActivity.

Android Studio: Переключение между Activity

Теперь мы возвращаемся к MainActivity, и к кнопке «Старт» пишем обработчик, для начала добавим строку:

Можно и в режиме дизайна, указать метод onClick:

Android Studio: Переключение между Activity

Сразу укажем кнопке ID (buttonBack).

Android Studio: Переключение между Activity

После, открываем MainActivity.java, и в метод Create добавляем строку:

Button buttonBack = (Button)findViewById(R.id.buttonBack);

Android Studio: Переключение между Activity

Далее необходимо навести каретку на (Button), вызвать контекстное меню зажав клавиши Alt+Enter и выбрать импорт класса.

Android Studio: Переключение между Activity

Теперь, сразу после, добавим строку:

Программа нам говорит об ошибке, чтобы её исправить нужно отредактировать строку:

public class MainActivity extends AppCompatActivity

и заменить её на:

public class MainActivity extends AppCompatActivity implements View.OnClickListener

Android Studio: Переключение между Activity

Теперь добавляем следующие строки:

И импортируем класс Intent (в противном случае выдаст ошибку Cannot find symbol class Intent).

Android Studio: Переключение между Activity

Шалость удалась, у нас есть работающая кнопка, которая переносит нас на новую Activity. Наполнять Activity содержимым буду уже в следующих обзорах.

Анимация перехода между Activity в Android – 5+ с использованием RecyclerView (Material Design)

Одним из наиболее интересных аспектов материального дизайна является визуальная преемственность окон приложения. С помощью нескольких строк кода новые интерфейсы API Lollipop позволяют реализовать интересный эффект перехода между двумя activity, благодаря бесшовной и непрерывной анимации . Это ломает границы классического поведения предыдущих версий Android и позволяет пользователю понять, как элементы переходят от одной точки к другой.

В этом уроке я покажу вам как добиться этого результата, делая пример приложения, в соответствии с принципами материального дизайна Google.

Необходимые условия

В этом учебнике я буду считать, что вы уже знакомы с Android разработкой и используете Android Studio. Необходимы базовые знания об интентах, жизненном цикле активности и новом элементе RecyclerView, появившемся с API 21, в июне 2014 года. Я не собираюсь погружаться в детали этого класса, но, если вы заинтересованы, вы можете найти большое объяснение в учебнике Tuts +.

1. Создаем Activity

Базовая структура приложения проста. Существует два вида activity, один основной, MainActivity.java, задача которого – отображение списка элементов, и второй, DetailActivity.java, который будет показать детали элемента, выбранного в списке MainActivity.java.

Шаг 1: RecyclerView

Чтобы отобразить список элементов, основной вид activity будет использовать RecyclerView. Первое, что вам нужно сделать: добавьте следующую строку в разделе зависимостей в build.grade файл проекта для включения обратной совместимости:

compile 'com.android.support:recyclerview-v7:+'
Шаг 2: Определение данных

Для краткости мы не создаем базу данных или аналогичный источник данных для приложения. Вместо этого, мы будем использовать пользовательский класс, Contact . Каждый элемент будет иметь имя, цвет и основную контактную информацию, связанную с ней. Вот как выглядит реализация класса Contact :

public class Contact < // The fields associated to the person private final String mName, mPhone, mEmail, mCity, mColor; Contact(String name, String color, String phone, String email, String city) < mName = name; mColor = color; mPhone = phone; mEmail = email; mCity = city; >// This method allows to get the item associated to a particular id, // uniquely generated by the method getId defined below public static Contact getItem(int id) < for (Contact item : CONTACTS) < if (item.getId() == id) < return item; >> return null; > // since mName and mPhone combined are surely unique, // we don't need to add another id field public int getId() < return mName.hashCode() + mPhone.hashCode(); >public static enum Field < NAME, COLOR, PHONE, EMAIL, CITY >public String get(Field f) < switch (f) < case COLOR: return mColor; case PHONE: return mPhone; case EMAIL: return mEmail; case CITY: return mCity; case NAME: default: return mName; >> >

Нам нужно заполнить его некоторыми данными. В верхней части класса контакта добавьте следующий фрагмент кода для заполнения набора данных.

public static final Contact[] CONTACTS = new Contact[] < new Contact("John", "#33b5e5", "+01 123456789", "john@example.com", "Venice"), new Contact("Valter", "#ffbb33", "+01 987654321", "valter@example.com", "Bologna"), new Contact("Eadwine", "#ff4444", "+01 123456789", "eadwin@example.com", "Verona"), new Contact("Teddy", "#99cc00", "+01 987654321", "teddy@example.com", "Rome"), new Contact("Ives", "#33b5e5", "+01 11235813", "ives@example.com", "Milan"), new Contact("Alajos", "#ffbb33", "+01 123456789", "alajos@example.com", "Bologna"), new Contact("Gianluca", "#ff4444", "+01 11235813", "me@gian.lu", "Padova"), new Contact("Fane", "#99cc00", "+01 987654321", "fane@example.com", "Venice"), >;
Шаг 3: Определение основных макетов

Макет основной activity является простым, потому что список заполнит весь экран. Макет включает в себя корневой RelativeLayout — но это так же может быть LinearLayout тоже — и RecyclerView как ее единственный потомок.

Поскольку RecyclerView упорядочивает дочерние элементы и ничего больше, необходимо разработать макет одного элемента списка. Мы хотим иметь цветной кружок слева от каждого элемента списка контактов, так что вы сначала должны определить drawable circle.xml.

Теперь у вас есть все элементы, необходимые для определения макета элемента списка.

Шаг 4: отображение данных с помощью RecyclerView

Теперь нужно написать RecyclerView.ViewHolder и RecyclerView.Adapter и объявить необходимые объекты в методе oncreate основной activity.

RecyclerView.ViewHolder должен обрабатывать клики, поэтому необходимо добавить обработчик.

public class RecyclerClickListener implements RecyclerView.OnItemTouchListener < private OnItemClickListener mListener; GestureDetector mGestureDetector; public interface OnItemClickListener < public void onItemClick(View view, int position); >public RecyclerClickListener(Context context, OnItemClickListener listener) < mListener = listener; mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() < @Override public boolean onSingleTapUp(MotionEvent e) < return true; >>); > @Override public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) < View childView = view.findChildViewUnder(e.getX(), e.getY()); if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) < mListener.onItemClick(childView, view.getChildPosition(childView)); return true; >return false; > @Override public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) < >>

Создадим класс DataManager, унаследованный от RecyclerView.Adapter. Он отвечает за загрузку данных и заполнение ними списка. Здесь мы также инициализируем RecyclerView.ViewHolder.

public class DataManager extends RecyclerView.Adapter  < public static class RecyclerViewHolder extends RecyclerView.ViewHolder < TextView mName, mPhone; View mCircle; RecyclerViewHolder(View itemView) < super(itemView); mName = (TextView) itemView.findViewById(R.id.CONTACT_name); mPhone = (TextView) itemView.findViewById(R.id.CONTACT_phone); mCircle = itemView.findViewById(R.id.CONTACT_circle); >> @Override public RecyclerViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) < View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.contact_item, viewGroup, false); return new RecyclerViewHolder(v); >@Override public void onBindViewHolder(RecyclerViewHolder viewHolder, int i) < // get the single element from the main array final Contact contact = Contact.CONTACTS[i]; // Set the values viewHolder.mName.setText(contact.get(Contact.Field.NAME)); viewHolder.mPhone.setText(contact.get(Contact.Field.PHONE)); // Set the color of the shape GradientDrawable bgShape = (GradientDrawable) viewHolder.mCircle.getBackground(); bgShape.setColor(Color.parseColor(contact.get(Contact.Field.COLOR))); >@Override public int getItemCount() < return Contact.CONTACTS.length; >>

Наконец, добавьте следующий код в метод oncreate, ниже setContentView. Основной вид activity готов.

RecyclerView rv = (RecyclerView) findViewById(R.id.rv); // layout reference LinearLayoutManager llm = new LinearLayoutManager(this); rv.setLayoutManager(llm); rv.setHasFixedSize(true); // to improve performance rv.setAdapter(new DataManager()); // the data manager is assigner to the RV rv.addOnItemTouchListener( // and the click is handled new RecyclerClickListener(this, new RecyclerClickListener.OnItemClickListener() < @Override public void onItemClick(View view, int position) < // STUB: // The click on the item must be handled >>));

Так будет выглядеть приложение после запуска.

first_activity-600-wide

2. Создание Details Activity

Шаг 1: Макет

Вторая activity гораздо проще. Она принимает идентификатор контакта и отображает дополнительную информацию.

С точки зрения дизайна, макет этой activity является критическим, поскольку это наиболее важная часть приложения. Но что касается XML, то это тривиально. Макет – это несколько экземпляров TextView расположенных в определенном порядке, с использованием LinearLayout и RelativeLayout. Код макета выглядит так:

Шаг 2: отправка и получение ID через Intent Extras

Поскольку эти два вида деятельности связаны с intent, необходимо отправить второй activity данные о контакте, для которого мы хотим получить подробную информацию.

Одним из вариантов может быть использование позиции переменной в качестве ссылки. Положение элемента в списке соответствует позиции элемента в массиве, поэтому не должно быть ничего плохого в использовании ее в виде уникальной ссылки.

Это будет работать, но если по каким-то причинам набор данных будет изменен во время выполнения, ссылка не будет соответствовать интересующему вас элементу списка. Именно поэтому лучше использовать идентификатор. Его можно получить с помощью метода getId в классе Contact.

Изменим обработчик нажатия элементов списка onItemClick, как показано ниже.

@Override public void onItemClick(View view, int position)

В DetailsActivity будем получать информацию от Intent Extras и строить нужный объект используя ID в качестве ссылки. Это показано в следующем блоке кода.

// Before the onCreate public final static String ; public Contact mContact; // In the onCreate, after the setContentView method mContact = Contact.getItem(getIntent().getIntExtra(ID, 0));

Как и прежде в методе RecyclerViewHolder onCreateViewHolder, инициализируем View, используя метод findViewById, и заполняем его используя метод setText. Например, чтобы настроить поле “имя”, мы поступаем следующим образом:

mName = (TextView) findViewById(R.id.DETAILS_name); mName.setText(mContact.get(Contact.Field.NAME));

Процесс аналогичен и для других полей. Вторая activity готова.

second_activity-600-wide

3. Анимация переходов

Мы наконец добрались до основной части урока, где мы будем оживлять два вида activity, используя новый способ анимации перехода между ними.

Шаг 1: Настройка Вашего Проекта

Первое, что вам нужно сделать, это изменить вашу тему в style.xml файле в values-v21 папке. Таким образом, вы подключите контент переходов для View, которые не являются общими между двумя activity.

 

Обратите внимание, что в настройках вашего проекта targetSdkVersion и compileSdkVersion должны быть установлены не ниже 21.

Шаг 2: Присвойте имена переходам в Layout файлах

После того, как вы отредактировали ваш style.xml файл, вы должны указать на отношение общих элементов между двумя activity.

В нашем примере activity имеют общие View, содержащие имя контакта, один из номеров телефона, и цветной круг. Для каждого из них, вы должны указать общее название перехода. Для этого добавим в strings.xml файл ресурсов следующие строки:

transition:NAME transition:CIRCLE transition:PHONE

Затем, для каждой из трех пар, в коде макета добавьте атрибут аndroid:transitionName с соответствующим значением. Для цветного круга, например, код выглядит так:

Благодаря этому атрибуту, Android будет знать, какие View общие между двумя видами activity и будет правильно анимировать переход. Повторите тот же процесс для двух других View.

Шаг 3: настроить intent

С точки зрения программирования нужно прикрепить определенный ActivityOptions bundle в intent. Нам нужен метод makeSceneTransitionAnimation, который принимает в качестве параметра контекст приложения и нужные нам общие элементы. В RecyclerView в методе onItemClick , изменим ранее определенный intent:

@Override public void onItemClick(View view, int position) < Intent intent = new Intent(MainActivity.this, DetailsActivity.class); intent.putExtra(DetailsActivity.ID, Contact.CONTACTS[position].getId()); ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation( // the context of the activity MainActivity.this, // For each shared element, add to this method a new Pair item, // which contains the reference of the view we are transitioning *from*, // and the value of the transitionName attribute new Pair(view.findViewById(R.id.CONTACT_circle), getString(R.string.transition_name_circle)), new Pair(view.findViewById(R.id.CONTACT_name), getString(R.string.transition_name_name)), new Pair(view.findViewById(R.id.CONTACT_phone), getString(R.string.transition_name_phone)) ); ActivityCompat.startActivity(MainActivity.this, intent, options.toBundle());

Для каждого общего элемента, который будет анимирован, необходимо добавить к методу makeSceneTransitionAnimation новый объект Pair, имеющий два значения, первое это ссылка на View, второе является значением атрибута transitionName.

Будьте осторожны при импорте класса Pair. Вам нужно будет включить в android.support.v4.util пакет, а не android.util пакет. Также, не забывайте использовать метод ActivityCompat.startActivity вместо startActivity, потому что иначе не сможете запустить приложение на средах с API ниже 16.

Вот и все. Мы закончили. Это так просто.

Вывод

В этом уроке мы узнали, как сделать красивый и плавный переход между двумя видами activity, которые разделяют одно или несколько общих элементов, который обеспечивает визуальную преемственность.

Анимация перехода в этом приложении не будет работать на устройствах с версией Android ниже 5.0. К сожалению, из соображений быстродействия приложений библиотека совместимости не обеспечивает полную обратную совместимость с этими эффектами перехода.

Бонус: Стилистические Детали

Чтобы приложение выглядело в лучших традициях Material Design, как показано на предыдущих скриншотах, вам также нужно будет изменить цвета вашей темы. Измените основную тему из папки values-v21, чтобы получить хороший результат:

 

Перевод источника. Автор урока Gianluca Segato. Скачать исходный код проекта

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *