Эта статья является частью нашего Академического курса под названием Android UI Design — Основы .
В этом курсе вы познакомитесь с основами дизайна пользовательского интерфейса Android. Вы поймете пользовательский ввод, представления и макеты, а также адаптеры и фрагменты. Проверьте это здесь !
Содержание
1. Обзор
В этой статье мы рассмотрим некоторые мультимедийные и графические аспекты в Android. Android SDK предоставляет набор API для обработки мультимедийных файлов, таких как аудио, видео и изображения. Кроме того, SDK предоставляет другие наборы API, которые помогают разработчикам реализовывать интересные графические эффекты, такие как анимация и так далее.
Современные смартфоны и планшеты имеют все большую емкость, поэтому мы можем хранить музыкальные файлы, видеофайлы, изображения и т. Д. Важна не только емкость, но и камера высокого разрешения, позволяющая делать впечатляющие фотографии. В этом контексте Multimedia API играет важную роль.
2. Мультимедийный API
Android поддерживает широкий список аудио, видео и графических форматов. Вы можете посмотреть здесь, чтобы иметь идею; просто назвать несколько поддерживаемых форматов:
аудио
- MP3
- MIDI
- Ворбис (эс: мкв)
видео
- H.263
- MPEG-4 SP
Изображений
- JPEG
- GIF
- PNG
Кроме того, Android может обрабатывать локальные файлы, то есть файлы, которые хранятся внутри смартфона или планшета или удаленного файла с использованием потоковой передачи данных. Мы можем использовать эти возможности для создания очень интересных приложений.
Все классы, предоставляемые Android SDK, которые мы можем использовать для добавления мультимедийных возможностей в наши приложения, находятся в пакете android.media
. В этом пакете класс сердца называется MediaPlayer
. Этот класс имеет несколько методов, которые мы можем использовать для воспроизведения аудио и видео файлов, хранящихся на нашем устройстве или передаваемых с удаленного сервера.
Этот класс реализует конечный автомат с четко определенными состояниями, и мы должны знать их перед воспроизведением файла. Упрощая диаграмму состояний, как показано в официальной документации, мы можем определить эти макро-состояния:
- Состояние бездействия: когда мы создаем новый экземпляр класса MediaPlayer.
- Состояние инициализации: это состояние срабатывает, когда мы используем
setDataSource
для установки источника информации, который должен использоватьMediaPlayer
. - Подготовленное состояние: В этом состоянии подготовительные работы завершены. Мы можем войти в это состояние, вызывая метод
prepareAsync
илиprepareAsync
. В первом случае после возврата метода состояние переходит в состояние «Prepared
. В асинхронном режиме мы должны реализовать прослушиватель, который будет уведомлен, когда система будет готова и состояние перейдет в состояние «Prepared
. Мы должны помнить, что при вызове методаprepare
все приложение может зависнуть, прежде чем метод вернется, потому что метод может занять много времени, прежде чем он завершит свою работу, особенно когда данные передаются с удаленного сервера. Мы должны избегать вызова этого метода в главном потоке, потому что это может вызвать проблему ANR (приложение не отвечает). КогдаMediaPlayer
находится в подготовленном состоянии, мы можем воспроизвести наш файл, приостановить или остановить его. - Завершенное состояние: достигнут конец потока.
Мы можем воспроизвести файл несколькими способами:
1
2
3
4
5
6
|
// Raw audio file as resource MediaPlayer mp = MediaPlayer.create( this , R.raw.audio_file); // Local file MediaPlayer mp1 = MediaPlayer.create( this , Uri.parse( "file:///...." )); // Remote file |
или мы можем использовать setDataSource
следующим образом:
1
2
|
MediaPlayer mp3 = new MediaPlayer(); |
После того, как мы создали наш MediaPlayer
мы можем «подготовить» его:
1
|
mp3.prepare(); |
и наконец мы можем сыграть это:
1
|
mp3.start(); |
Пожалуйста, имейте в виду вышеизложенные замечания по подготовке государства Согласно им, мы можем использовать асинхронную операцию, чтобы не останавливать основной поток. В этом случае имеем:
01
02
03
04
05
06
07
08
09
10
|
// Remote file mp2.setAudioStreamType(AudioManager.STREAM_MUSIC); mp2.setOnCompletionListener( new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { mp.start(); } }); mp2.prepareAsync(); |
Мы использовали слушателя, чтобы получать уведомления, когда MediaPlayer
находится в подготовленном состоянии, чтобы мы могли начать воспроизведение. В конце, когда нам больше не нужен экземпляр MediaPlayer
, мы должны выпустить его:
1
|
mp2.release(); |
2.1. Использование камеры Android
Если мы хотим добавить в наши приложения возможность фотографировать с помощью встроенной камеры смартфона, то лучшим способом будет использование Intent
. Например, предположим, что мы хотим запустить камеру, как только мы нажмем кнопку и покажем результат в нашем приложении.
В методе onCreate
нашей Activity
мы должны настроить прослушиватель Button
и при нажатии для onCreate
намерения:
1
2
3
4
5
6
7
8
9
|
Button b = (Button) findViewById(R.id.btn1); b.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { // Here we fire the intent to start the camera Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(i, 100 ); } }); |
В методе onActivityResult
мы извлекаем сделанный снимок и показываем результат:
1
2
3
4
5
6
|
@Override protected void onActivityResult( int requestCode, int resultCode, Intent data) { // This is called when we finish taking the photo Bitmap bmp = (Bitmap) data.getExtras().get( "data" ); iv.setImageBitmap(bmp); } |
Запустив приложение мы имеем:
В приведенном выше примере мы использовали эмулированную камеру.
3. Графика
К настоящему времени мы говорили о стандартных компонентах, которые мы можем использовать в нашем пользовательском интерфейсе. Это хорошо, но этого недостаточно, когда мы хотим разработать игру или приложение, которое требует графического содержимого. Android SDK предоставляет набор API для рисования пользовательской 2D и 3D графики. Когда мы пишем приложение, которое требует графики, мы должны учитывать, насколько интенсивно использование графики. Другими словами, может быть приложение, которое использует довольно статичную графику без сложных эффектов, и может быть другое приложение, которое использует интенсивные графические эффекты, такие как игры.
В соответствии с этим использованием, мы можем использовать различные методы:
- Canvas и Drawable: в этом случае мы можем расширить существующие виджеты пользовательского интерфейса, чтобы мы могли настроить их поведение или создать собственную 2D-графику, используя стандартный метод, предоставленный классом
Canvas
. - Аппаратное ускорение: мы можем использовать аппаратное ускорение при рисовании с помощью
Canvas
API. Это возможно с Android 3.0. - OpenGL: Android изначально поддерживает OpenGL с использованием NDK. Эта техника очень полезна, когда у нас есть приложение, которое интенсивно использует графический контент (например, игры).
Самым простым способом использования 2D-графики является расширение класса View
и переопределение метода onDraw
. Мы можем использовать эту технику, когда нам не нужно графически интенсивное приложение.
В этом случае мы можем использовать класс Canvas
для создания 2D-графики. Этот класс предоставляет набор методов, начинающихся с draw*
которые можно использовать для рисования различных фигур, таких как:
- линии
- круг
- прямоугольник
- овальный
- картина
- дуга
Например, давайте предположим, что мы хотим нарисовать прямоугольник. Мы создаем пользовательское представление и затем переопределяем метод onDraw
. Здесь мы рисуем прямоугольник:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public class TestView extends View { public TestView(Context context) { super (context); } public TestView(Context context, AttributeSet attrs, int defStyle) { super (context, attrs, defStyle); } public TestView(Context context, AttributeSet attrs) { super (context, attrs); } @Override protected void onDraw(Canvas canvas) { super .onDraw(canvas); Paint p = new Paint(); p.setColor(Color.GREEN); p.setStrokeWidth( 1 ); p.setStyle(Paint.Style.STROKE); canvas.drawRect( 5 , 5 , 120 , 120 , p); invalidate(); } } |
Как видно из приведенного выше кода, в методе onDraw
мы использовали метод drawRect
Canvas
. Обратите внимание, что мы использовали другой класс под названием Paint
. Этот класс определяет, как будет нарисована форма; он определяет его цвет, если он должен быть заполнен, ширину границы и так далее.
В этом случае макет выглядит так:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
android:layout_width = "match_parent" android:layout_height = "match_parent" android:paddingBottom = "@dimen/activity_vertical_margin" android:paddingLeft = "@dimen/activity_horizontal_margin" android:paddingRight = "@dimen/activity_horizontal_margin" android:paddingTop = "@dimen/activity_vertical_margin" tools:context = ".MainActivity" > < com.swa.customview.TestView android:layout_width = "wrap_content" android:layout_height = "wrap_content" /> </ RelativeLayout > |
Запустив приложение, мы имеем:
Предположим, мы хотим залить прямоугольник цветом градиента, поэтому метод onDraw
становится:
01
02
03
04
05
06
07
08
09
10
11
|
protected void onDraw(Canvas canvas) { super .onDraw(canvas); Paint p = new Paint(); p.setColor(Color.GREEN); p.setStrokeWidth( 1 ); p.setStyle(Paint.Style.FILL_AND_STROKE); LinearGradient lg = new LinearGradient(0F, 0F, 115F,115F, Color.GREEN, Color.YELLOW, TileMode.CLAMP); p.setShader(lg); canvas.drawRect( 5 , 5 , 120 , 120 , p); invalidate(); } |
Запустив приложение мы имеем:
Как мы уже говорили, начиная с Android 3.0 (API 11), мы можем использовать аппаратное ускорение. В этом случае, если мы хотим использовать его, мы должны изменить Manifest.xml
и добавить следующую строку:
1
|
< application android:hardwareAccelerated = "true" > |
или мы можем использовать его на уровне Activity
.
4. Drawable
В Android Drawable
— это графический объект, который можно отобразить на экране. С точки зрения API все объекты Drawable
производными от класса Drawable
. Они играют важную роль в программировании на Android, и мы можем использовать XML для их создания. Они отличаются от стандартных виджетов, потому что они не являются интерактивными, то есть они не реагируют на прикосновения пользователя.
Изображения, цвета, формы, объекты, которые изменяют свой аспект в соответствии с их состоянием, объекты, которые можно анимировать, — все это объекты для рисования. В Android в каталоге res
есть подкаталог, зарезервированный для Drawable
, он называется res/drawable
.
Под drawable
мы можем добавить двоичные файлы, такие как изображения или файлы XML.
Как мы видели в предыдущих статьях , мы можем создать несколько каталогов в соответствии с плотностью экрана, которую мы хотим поддерживать. Эти каталоги имеют имя вроде drawable-<>
.
Это очень полезно, когда мы используем изображения; в этом случае нам нужно создать несколько версий изображения: например, мы можем создать изображение для экрана с высоким разрешением или другое для экрана со средним разрешением. Как только мы R.drawable.file_name
наш файл в каталог drawable
, мы можем ссылаться на него в нашем классе, используя R.drawable.file_name
. Хотя очень просто добавить двоичный файл в один из этих каталогов, это вопрос копирования и вставки, если мы хотим использовать XML-файл, мы должны его создать.
Есть несколько типов рисования:
- Битовая карта
- Девять патч
- Список слоев
- Государственный список
- Список уровней
- Переходный
- Вставка для рисования
- Клип для рисования
- Масштабируемый
- Форма нарисованная
Интересным аспектом является то, что мы можем создавать такие элементы, используя XML или непосредственно из кода. Существует соответствие между показанными выше элементами и классом API. Мы можем добавить суффикс Drawable
и создать соответствующее имя класса: например, если соответствующий класс BitmapDrawable
Bitmap
— BitmapDrawable
и так далее.
Вы можете посмотреть здесь, если хотите получить больше информации. Мы не будем охватывать все эти объекты в этой статье, а только самые популярные.
4.1. Форма нарисованная
Это общая форма. Используя XML, мы должны создать файл с элементом shape в качестве root. Этот элемент в качестве атрибута называется android:shape
где мы определяем тип фигуры, такой как прямоугольник, овал, линия и кольцо. Мы можем настроить форму, используя дочерние элементы, такие как:
Например, предположим, что мы хотим создать овал со сплошным цветом фона. Мы создаем файл XML с именем, например, oval.xml
:
01
02
03
04
05
06
07
08
09
10
|
android:shape = "oval" > < solid android:color = "#FF0000" /> < size android:height = "100dp" android:width = "120dp" /> </ shape > |
Таким образом, мы создаем овальную форму, имеющую красный цвет фона и размер 120dpx100dp. Тогда мы можем сослаться на это в нашем файле макета:
1
2
3
4
5
|
< ImageView android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_centerInParent = "true" android:src = "@drawable/oval" /> |
Запустив приложение, мы получим:
Например, мы можем предположить, что хотим изменить внешний вид виджета « Button
. Мы хотим создать прямоугольник с закругленными углами и в качестве фона цвет градиента. Мы определяем фигуру в файле XML с именем round_corner.xml
и добавляем ее в drawable
dir:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
android:shape = "rectangle" > < stroke android:width = "2dp" android:color = "#00FF00" /> < gradient android:angle = "-90" android:endColor = "#FFFFFF" android:startColor = "#00FF00" android:type = "linear" /> < corners android:radius = "3dp" /> < padding android:bottom = "4dp" android:left = "4dp" android:right = "4dp" android:top = "4dp" /> </ shape > |
и в файле макета мы имеем:
1
2
3
4
5
6
|
< Button android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_centerInParent = "true" android:background = "@drawable/round_corner" android:text = "Click me" /> |
Запустив приложение, мы имеем:
Как мы видим, просто используя XML, мы можем изменить фон виджета или создать фигуры.
4.2. Государственный список
Этот нарисованный объект может отображать несколько нарисованных объектов в зависимости от состояния объекта. Это очень полезно, когда мы хотим настроить некоторый объект, который имеет внутренние состояния. Например, виджет « Button
является одним из этих объектов, он имеет несколько состояний: нажатие, фокусировка и т. Д.
В XML этот объект представлен тегом селектора. Этот тег имеет дочерние элементы item:
1
2
3
4
5
6
|
< item android:drawable = "" drawable1" android:state_pressed = "true" /> < item android:drawable = "" drawable2" android:state_focused = "true" /> </ selector > |
Давайте предположим, что мы хотим настроить виджет Button
в нашем макете при его нажатии. Кроме того, мы хотим изменить его фон на красный цвет градиента. Итак, первое, что мы делаем, это определяем две фигуры:
1
2
3
4
5
|
< solid android:color = "#00FF00" /> </ shape > |
green.xml
1
2
3
4
5
6
7
8
9
|
< gradient android:angle = "-90" android:endColor = "#FFFFFF" android:startColor = "#AA0000" android:type = "linear" /> </ shape > |
Как только у нас есть формы, мы можем назначить их различным состояниям объекта
1
2
3
4
5
6
|
< item android:drawable = "@drawable/red_gradient" android:state_pressed = "true" /> < item android:drawable = "@drawable/green" /> </ selector > |
Таким образом, мы назначаем рисование red_gradient при нажатии кнопки и рисование зеленого цвета в состоянии по умолчанию. Запустив приложение мы имеем:
4,3. Девять патч
Nine-patch image — это специальное фоновое изображение, размер которого можно изменить, чтобы в нем можно было просматривать содержимое. Вы можете посмотреть здесь, если хотите получить больше информации. Его можно использовать, когда мы хотим создать изображение, но мы не знаем точный размер содержимого View
.
Вкратце, при создании этого изображения мы определяем границы, которые можно растянуть, и статическую область. Android предоставляет инструмент, помогающий нам создавать изображения такого типа, расположенный в каталоге инструментов. Предположим, что мы хотим создать фон виджета Button
, мы можем создать изображение, подобное показанному ниже:
Теперь мы можем запустить draw9patch.bat
в каталоге инструментов. Теперь мы можем перетащить это изображение в открывшееся окно:
Окно разделено на две области: левая является «рабочим окном», а с правой стороны мы получаем конечный результат. Теперь нам нужно выбрать область изображения, которая может масштабироваться, мы можем сделать это, рисуя линии слева и сверху, как вы можете видеть на картинке:
Теперь мы устанавливаем область содержимого, выбирая правую и нижнюю часть изображения.
Мы видим на правой стороне конечный результат. Теперь мы можем сохранить нашу работу. Когда мы закончим, мы можем скопировать это изображение в res/drawable
нашего проекта Android.
Чтобы увидеть конечный эффект, мы можем создать макет, подобный показанному ниже:
01
02
03
04
05
06
07
08
09
10
11
12
13
|
< Button android:id = "@+id/btn1" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:background = "@drawable/stdbox" android:text = "This is a standard background with red border" /> < Button android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_below = "@id/btn1" android:layout_marginTop = "10dp" android:background = "@drawable/box" android:text = "This is a 9 patch background with red border" /> |
В первой кнопке мы использовали стандартное изображение — простое красное поле, как показано выше, в то время как во второй кнопке мы используем изображение с 9-patch
.
Запустив пример, который мы имеем:
Вы можете заметить, что 9-patch
изображения масштабируются лучше, чем стандартное изображение.
5. Загрузите исходный код
Это был урок о том, как использовать мультимедиа с Android. Вы можете скачать исходный код здесь: