Перемещение объектов android studio

Перемещение объектов android studio

В этом уроке мы научимся создавать движение объекта по экрану с полным контролем этого движения прикосновением пальца. У нас на экране будет находится всеми любимое изображение ic_launcher, которое можно будет передвигать по всему экрану в любую точку.

Начнем с создания нового проекта, выбираем Blank Activity, минимальная версия Android будет 2,2+.

Создадим нехитрый интерфейс приложения. Открываем файл activity_main.xml и добавим туда элемент ImageView:

Теперь переходим к написанию самой программы в MainActivity.java. Все происходящее будет вертеться вокруг использования двух вещей — RelativeLayout.LayoutParams и класса MotionEvent. С помощью RelativeLayout.LayoutParams мы запихнем наше изображение в определенные рамки (сделаем его размером 100*100) и будем изменять положение изображения, отслеживая новые координаты положения изображения на экране.

Класс MotionEvent описывает движение с помощью набора значений координат. Он состоит из определенных команд и числовых значений по осям координат, определяющим положение объекта. Например, когда пользователь впервые прикасается к экрану, вызывается команда ACTION_DOWN, а также набор значений X, Y, включающих координаты точки прикосновения.

Из класса MotionEvent у нас будет использовано 2 команды: MotionEvent.ACTION_DOWN — отслеживает факт прикосновения к объекту и начало движения, здесь будут определяться начальные координаты объекта, далее в работу вступает MotionEvent.ACTION_MOVE, в которой происходит динамическое изменение положения объекта за время жеста прикосновения и содержится точка последней остановки, установленная после завершения действия MotionEvent.ACTION_DOWN.

Добавляем в файл MainActivity.java следующий код:

Ну а теперь проверим, работает ли программа, получилось ли желаемое управляемое движение. Запускаем приложение и любуемся результатом:

Наш Андруша успешно двигается по всему экрану, надеюсь у вас также :).

Источник

Пишем игру для Android. Часть 2 — Вывод рисунка на экран и его перемещение

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

Сегодня мы займемся графикой. Вывод изображения на экран телефона в Android задача почти тривиальная. Не будем ходить вокруг да около, а сразу займемся делом. Для начала выведем изображение робота в верхнем левом углу экрана. Для работы с графикой предпочтительно использовать png формат. Наш рисунок будет называтьсяdroid_1.png и иметь размер 20×20 пикселей. Для того, чтобы с рисунком стало можно работать из приложения, просто скопируйте его в папку/res/drawable-mdpi вашего проекта. Проще всего это сделать, перетащив файлик в соответствующую папку в дереве проектов в Eclipse.

Кстати, обратите внимание, в проекте существует несколько папок drawable. Дело в том, что ваша программа может запускаться на устройствах с разными размерами и разрешениями экрана, поэтому имеет смысл подготовить несколько наборов графических файлов, отличающихся размером картинок. В зависимости от того, где будет работать программа, выбирается тот или иной набор. Я выбрал папку drawable-mdpi, которая соответствует устройствам со средней плотностью точек на экране.

Читайте также:  Com google android gallery3d

Откройте файл MainGamePanel.java и измените метод onDraw(Canvas canvas)

Метод drawBitmap выводит изображение droid_1.png на экран, причем левый верхний угол этого изображения помещается в точку с координатами x=10, y=15 (напоминаю, ось x направлена вправо, y — вниз, начало координат — верхний левый угол экрана). Для вывода изображения мы использовали id нашего ресурса (картинки внутри папки res), то есть droid_1. При копировании картинки в папку /res/drawable-mdpi Eclipse автоматически внес изменение в файл R.java и имя файла стало его идентификатором. В случае, если вы скопировали файл в папку проекта не через Eclipse, а стандартными средствами вашей операционной системы, то файл R.java не изменится. Более того, если Вы раскроете папку res, то не увидите там только что скопированного файла. Чтобы обновить проект щелкните мышкой по папке res в дереве проектов в Eclipse и нажмите кнопку F5, либо выберите Refresh из контекстного меню.

Помимо метода onDraw нам понадобится также внести некоторые изменения в поток MainThread. Откройте файл MainThread.java и измените метод run()

Как видите, мы объявили переменную canvas типа Canvas. Canvas очень распространенная в графических библиотеках концепция. Наиболее адекватно на русский язык canvas переводится как холст. Можно воспринимать этот объект, как лист бумаги, на который можно нанести рисунок. Объект Canvas содержит ряд команд, позволяющие выполнять различные операции рисования.

Мы пытаемся инициализировать эту переменную с помощью метода surfaceHolder.lockCanvas() — то есть связать переменную с активной поверхностью view. Этот код помещен в операторные скобки try <. >finally < . >. Если внутри блока try произойдет ошибка, ну например по каким-то причинам нам не удастся заблокировать canvas под себя, то программа не завершится, а выполнится код в блоке finally. Если нам удастся получить в свое распоряжение Canvas, мы передаем его в качестве параметра методу gamePanel.onDraw, внутри которого и осуществляется рисование.

Обратите также внимание на блок synchronised. Включив этот блок в наш код, мы указываем, что получаем surfaceHolder в свое полное распоряжение, блокируем его. Это значит, что до тех пор, пока блок synchronised не закончится, никто другой параллельно не сможет работать с этим объектом.

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

Перемещение изображения

Итак, мы научились выводить картинку на экран, давайте заставим ее двигаться. Как? Используем наши пальцы. Напишем простую реализацию drag and drop функции (кстати, более подробно об drag and drop рассказанов этой статье). Чтобы переместить рисунок, мы должны щелкнуть по нему и переместить в точку, соответствующую координатам касания. После того, как пользователь отрывает палец от экрана, координаты этой точки запоминаются и рисунок выводится туда.

Давайте создадим для нашего робота отдельный класс Droid.java, в котором определим поля для хранения координат и, собственно, рисунка.

Класс очень простой. В нем определены три поля (x,y и bitmap), методы get и set, позволяющие считывать и записывать их значения, а также конструктор, внутри которого происходит начальная инициализация полей класса.

Нам также понадобятся переменные, для хранения состояния робота. В рамках решаемой в данный момент задачи робот может находиться в одном из двух состояний «перетаскивается» или «не перетаскивается». Определить эти состояния можно с помощью логической переменной touched. В момент, когда пользователь коснулся изображения робота, эта переменная должна принимать значение true. False она примет лишь в момент, когда палец будет снят с экрана.

Читайте также:  Scan app with android

Давайте немного доработаем класс Droid. Добавим в него метод, осуществляющий рисование draw и метод обработки касания handleActionDown.

Методы draw и handleActionDown обсудим чуть позже, а пока давайте немного поправим код в файле MainGamePanel.java.

В конструкторе класса MainGamePanel мы создали объект droid. В методе onTouchEvent обрабатывается событие касание экрана (MotionEvent.ACTION_DOWN). Если касание произошло, мы вызываем метод handleActionDown, куда передаем координаты. Приведем еще раз листинг этого метода.

Мы сравниваем координаты касания с координатами робота, и если касание происходит внутри прямоугольной области, соответствующей картинке робота, мы изменяем его состояние setTouched(true); в противном случае меняем на false.

Вернемся к методу onTouched. Помимо события MotionEvent.ACTION_DOWN, там обрабатывается событие MotionEvent.ACTION_MOVE. Оно возникает при перемещении пальца по экрану. Внутри обработчика этого события, мы проверяем состояние робота (значение поля touched) и если оно равно true — обновляем координаты робота. В обработчике события MotionEvent.ACTION_UP мы переводим состояние робота в false.

Перейдем к методу Draw. Как помните, он вызывается у нас на каждом шаге игрового цикла. Внутри этого метода мы красим экран в черный цвет, а затем вызываем метод draw объекта droid, который выводит робота на экран.

Можете запустить проект и попытаться поперетаскивать робота по экрану.

Самостоятельное перемещение робота

Давайте теперь придадим нашему роботу самостоятельности и заставим его путешествовать по экрану без вмешательства пользователя. Робот не должен выходить за пределы экрана. Если он дошел до края — он должен изменить направление своего движения. Если наш объект движется самостоятельно — у него должна иметься какая-то скорость. Величина этой скорости влияет на изменение координат. Для понятия «скорость» мы реализуем собственный класс Speed.

Создайте класс Speed.java

Робот имеет горизонтальную и вертикальную составляющую скорости. На каждом шаге цикла к текущей координате робота будим прибавлять соответствующую скорость (на самом деле в физическом смысле правильнее было бы прибавлять величину скорости, умноженную на время прошедшее с прошлой операции перемещения объекта, но мы в целях упрощения не будем так сильно заморачиваться). В конструкторе переменным vx и vy мы присвоили значение 1, то есть на каждом шаге игрового цикла робот будет смещаться на 1 пиксел. Если vx > 0 — робот движется вправо, если vx 0-вниз, vy

Источник

Drag и Swipe в RecyclerView. Часть 2: контроллеры перетаскивания, сетки и пользовательские анимации

В первой части мы рассмотрели ItemTouchHelper и реализацию ItemTouchHelper.Callback, которая добавляет базовые функции drag & drop и swipe-to-dismiss в RecyclerView . В этой статье мы продолжим то, что было сделано в предыдущей, добавив поддержку расположения элементов в виде сетки, контроллеры перетаскивания, выделение элемента списка и пользовательские анимации смахивания (англ. swipe).

Контроллеры перетаскивания

При создании списка, поддерживающего drag & drop, обычно реализуют возможность перетаскивания элементов по касанию. Это способствует понятности и удобству использования списка в «режиме редактирования», а также рекомендуется material-гайдлайнами. Добавить контроллеры перетаскивания в наш пример сказочно легко.

Сперва обновим layout элемента (item_main.xml).

Изображение, используемое для контроллера перетаскивания, можно найти в Material Design иконках и добавить в проект с помощью удобного плагина генератора иконок в Android Studio.

Как кратко упоминалось в прошлой статье, вы можете использовать ItemTouchHelper.startDrag(ViewHolder) , чтобы программно запустить перетаскивание. Итак, всё, что нам нужно сделать, это обновить ViewHolder , добавив контроллер перетаскивания, и настроить простой обработчик касаний, который будет вызывать startDrag() .

Нам понадобится интерфейс для передачи события по цепочке:

Читайте также:  Формат андроид как форматировать флешку

Затем определите ImageView для контроллера перетаскивания в ItemViewHolder :

и обновите RecyclerListAdapter :

RecyclerListAdapter теперь должен выглядеть примерно так.

Всё, что осталось сделать, это добавить OnStartDragListener во фрагмент:

RecyclerListFragment теперь должен выглядеть следующим образом. Теперь, когда вы запустите приложение, то сможете начать перетаскивание, коснувшись контроллера.

Выделение элемента списка

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

Чтобы реализовать это в нашем примере, просто добавьте фон (свойство background ) в корневой FrameLayout элемента item_main.xml или установите его в конструкторе RecyclerListAdapter.ItemViewHolder. Это будет выглядеть примерно так:

Выглядит круто, но, возможно, вы захотите контролировать ещё больше. Один из способов сделать это — позволить ViewHolder обрабатывать изменения состояния элемента. Для этого ItemTouchHelper.Callback предоставляет ещё два метода:

  • onSelectedChanged(ViewHolder, int) вызывается каждый раз, когда состояние элемента меняется на drag (ACTION_STATE_DRAG) или swipe (ACTION_STATE_SWIPE). Это идеальное место, чтобы изменить состояние view -компонента на активное.
  • clearView(RecyclerView, ViewHolder) вызывается при окончании перетаскивания view -компонента, а также при завершении смахивания (ACTION_STATE_IDLE). Здесь обычно восстанавливается изначальное состояние вашего view -компонента.

А теперь давайте просто соберём всё это вместе.

Сперва создайте интерфейс, который будут реализовывать ViewHolders :

Затем в SimpleItemTouchHelperCallback реализуйте соотвутствующие методы:

Теперь осталось только, чтобы RecyclerListAdapter.ItemViewHolder реализовал ItemTouchHelperViewHolder :

В этом примере мы просто добавляем серый фон во время активности элемента, а затем его удаляем. Если ваш ItemTouchHelper и адаптер тесно связаны, вы можете легко отказаться от этой настройки и переключать состояние view -компонента прямо в ItemTouchHelper.Callback .

Сетки

Если теперь вы попытаетесь использовать GridLayoutManager , вы увидите, что он работает неправильно. Причина и решение проблемы просты: мы должны сообщить нашему ItemTouchHelper , что мы хотим поддерживать перетаскивание элементов влево и вправо. Ранее в SimpleItemTouchHelperCallback мы уже указывали:

Единственное изменение, необходимое для поддержки сеток, заключается в добавлении соответствующих флагов:

Тем не менее, swipe-to-dismiss не очень естественное поведение для элементов в виде сетки, поэтому swipeFlags разумнее всего обнулить:

Чтобы увидеть рабочий пример GridLayoutManager , смотрите RecyclerGridFragment. Вот как это выглядит при запуске:

Пользовательские анимации смахивания

ItemTouchHelper.Callback предоставляет действительно удобный способ для полного контроля анимации во время перетаскивания или смахивания. Поскольку ItemTouchHelper — это RecyclerView.ItemDecoration, мы можем вмешаться в процесс отрисовки view -компонента похожим образом. В следующей части мы разберём этот вопрос подробнее, а пока посмотрим на простой пример переопределения анимации смахивания по умолчанию, чтобы показать линейное исчезновение.

Параметры dX и dY — это текущий сдвиг относительно выделенного view -компонента, где:

  • -1.0f — это полное смахивание справа налево (от ItemTouchHelper.END к ItemTouchHelper.START )
  • 1.0f — это полное смахивание слева направо (от ItemTouchHelper.START к ItemTouchHelper.END )

Важно вызывать super для любого actionState , который вы не обрабатываете, для того, чтобы запускалась анимация по умолчанию.

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

Заключение

На самом деле, настройка ItemTouchHelper — это довольно весело. Чтобы не увеличивать объём этой статьи, я разделил её на несколько.

Исходный код

Весь код этой серии статей смотрите на GitHub-репозитории Android-ItemTouchHelper-Demo. Эта статья охватывает коммиты от ef8f149 до d164fba.

Источник

Оцените статью