Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Программное создание LinearLayout



Создание LinearLayout в коде MainActivity:

package com.example.eugene.layoutapp; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.LinearLayout; import android.widget.TextView; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) {   super.onCreate(savedInstanceState);    LinearLayout linearLayout = new LinearLayout(this);    linearLayout.setOrientation(LinearLayout.VERTICAL);    TextView textView1 = new TextView(this);    textView1.setText(" Hello" );    linearLayout.addView(textView1, new LinearLayout.LayoutParams           (LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));    TextView textView2 = new TextView(this);    textView2.setText(" Android" );    linearLayout.addView(textView2, new LinearLayout.LayoutParams           (LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));            setContentView(linearLayout); }}

RelativeLayout

RelativeLayout представляет объект ViewGroup, который располагает дочерние элементы относительно позиции других дочерних элементов разметки или относительно области самой разметки RelativeLayout. Используя относительное позиционирование, мы можем установить элемент по правому краю или в центре или иным способом, который предоставляет данный контейнер. Для установки элемента в файле xml мы можем применять следующие атрибуты:

  • android: layout_above: располагает элемент над элементом с указанным Id
  • android: layout_below: располагает элемент под элементом с указанным Id
  • android: layout_toLeftOf: располагается слева от элемента с указанным Id
  • android: layout_toRightOf: располагается справа от элемента с указанным Id
  • android: layout_alignBottom: выравнивает элемент по нижней границе другого элемента с указанным Id
  • android: layout_alignLeft: выравнивает элемент по левой границе другого элемента с указанным Id
  • android: layout_alignRight: выравнивает элемент по правой границе другого элемента с указанным Id
  • android: layout_alignTop: выравнивает элемент по верхней границе другого элемента с указанным Id
  • android: layout_alignBaseline: выравнивает базовую линию элемента по базовой линии другого элемента с указанным Id
  • android: layout_alignParentBottom: если атрибут имеет значение true, то элемент прижимается к нижней границе контейнера
  • android: layout_alignParentRight: если атрибут имеет значение true, то элемент прижимается к правому краю контейнера
  • android: layout_alignParentLeft: если атрибут имеет значение true, то элемент прижимается к левому краю контейнера
  • android: layout_alignParentTop: если атрибут имеет значение true, то элемент прижимается к верхней границе контейнера
  • android: layout_centerInParent: если атрибут имеет значение true, то элемент располагается по центру родительского контейнера
  • android: layout_centerHorizontal: при значении true выравнивает элемент по центру по горизонтали
  • android: layout_centerVertical: при значении true выравнивает элемент по центру по вертикали

Например, позиционирование относительно контейнера RelativeLayout:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <? xml version=" 1.0" encoding=" utf-8"? > < RelativeLayout xmlns: android=" http: //schemas.android.com/apk/res/android" android: id=" @+id/activity_main" android: layout_width=" match_parent" android: layout_height=" match_parent" >   < TextView android: text=" Left Top" android: layout_height=" wrap_content" android: layout_width=" wrap_content" android: textSize=" 26sp" android: layout_alignParentLeft=" true" android: layout_alignParentTop=" true" />   < TextView android: text=" Right Top" android: layout_height=" wrap_content" android: layout_width=" wrap_content" android: textSize=" 26sp" android: layout_alignParentRight=" true" android: layout_alignParentTop=" true" />   < TextView android: text=" Left Bottom" android: layout_height=" wrap_content" android: layout_width=" wrap_content" android: textSize=" 26sp" android: layout_alignParentLeft=" true" android: layout_alignParentBottom=" true" />   < TextView android: text=" Right Bottom" android: layout_height=" wrap_content" android: layout_width=" wrap_content" android: textSize=" 26sp" android: layout_alignParentRight=" true" android: layout_alignParentBottom=" true" /> < /RelativeLayout>

Для позиционирования относительно другого элемента, нам надо указать id этого элемента. Так, поместим на RelativeLayout текстовое поле и кнопку:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <? xml version=" 1.0" encoding=" utf-8"? > < RelativeLayout xmlns: android=" http: //schemas.android.com/apk/res/android" android: id=" @+id/activity_main" android: layout_width=" match_parent" android: layout_height=" match_parent" >   < EditText android: id=" @+id/edit_message" android: layout_width=" match_parent" android: layout_height=" wrap_content" android: layout_centerInParent=" true" /> < Button android: layout_width=" wrap_content" android: layout_height=" wrap_content" android: text=" Отправить" android: layout_alignRight=" @id/edit_message" android: layout_below=" @id/edit_message" /> < /RelativeLayout>

В данном случае поле EditText располагается по центру в RelativeLayout, а кнопка помещается под EditText и выравнивается по его правой границе:

Создадим элемент RelativeLayout программно в коде MainActivity:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package com.example.eugene.layoutapp;   import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.Button; import android.widget.EditText; import android.widget.RelativeLayout;   public class MainActivity extends AppCompatActivity {   @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);   RelativeLayout relativeLayout = new RelativeLayout(this);   EditText editText = new EditText(this); editText.setId(1);   Button button = new Button(this); button.setText(" Отправить" );   // устанавливаем параметры положения для EditText RelativeLayout.LayoutParams editTextParams = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT ); editTextParams.addRule(RelativeLayout.CENTER_IN_PARENT); relativeLayout.addView(editText, editTextParams);   // устанавливаем параметры положения для Button RelativeLayout.LayoutParams buttonParams = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT ); buttonParams.addRule(RelativeLayout.BELOW, editText.getId()); buttonParams.addRule(RelativeLayout.ALIGN_RIGHT, editText.getId()); relativeLayout.addView(button, buttonParams);   setContentView(relativeLayout); } }

Чтобы задать положение элемента в контейнере, применяется класс RelativeLayout.LayoutParams. Через конструктор устанавливаются значения для для ширины и высоты. Например, у элемента EditText для ширины устанавливается значение MATCH_PARENT, а для высоты - WRAP_CONTENT.

С помощью метода addRule() мы можем добавлять дополнительные правила для позиционирования элемента. Этот метод в качестве параметра принимает числовую константу, которая представляет параметр позиционирования и которая аналогична атрибуту. Например, атрибуту android: layout_centerInParent будет соответствовать константа CENTER_IN_PARENT, а атрибуту android: layout_alignRight константа ALIGN_RIGHT.

Стоит отметить, что в целях упрощения кода для установки id у EditText вызывается метод setId, в который передается простое число. И Android Studio может подчеркивать данный метод в качестве ошибки, но по факту здесь ошибки нет, однако в реальности, для определения всех идентификаторов, как правило, используются отдельные файлы ресурсов.

Затем установленный id передается в качестве второго параметра в метод addRule при установке правил для кнопки:

1 buttonParams.addRule(RelativeLayout.BELOW, editText.getId());

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


Gravity и layout_gravity

Для управления позиционированием элемента при определении интерфейса мы можем использовать такие атрибуты как gravity и layout_gravity.


Gravity

Атрибут gravity задает позиционирование содержимого внутри объекта. Он может принимать следующие значения:

· top: элементы размещаются вверху

· bottom: элементы размещаются внизу

· left: элементы размещаются в левой стороне

· right: элементы размещаются в правой стороне контейнера

· center_vertical: выравнивает элементы по центру по вертикали

· center_horizontal: выравнивает элементы по центру по горизонтали

· center: элементы размещаются по центру

· fill_vertical: элемент растягивается по вертикали

· fill_horizontal: элемент растягивается по горизонтали

· fill: элемент заполняет все пространство контейнера

· clip_vertical: обрезает верхнюю и нижнюю границу элементов

· clip_horizontal: обрезает правую и левую границу элементов

· start: элемент позиционируется в начале (в верхнем левом углу) контейнера

· end: элемент позиционируется в конце контейнера(в верхнем правом углу)

Например, поместим текст в самый низ в элементе TextView:

< RelativeLayout xmlns: android=" http: //schemas.android.com/apk/res/android" android: layout_width=" match_parent" android: layout_height=" match_parent" >    < TextView       android: gravity=" bottom"        android: layout_width=" match_parent"        android: layout_height=" 200px"        android: text=" Hello Android 7"        android: background=" #e8eaf6" /> < /RelativeLayout>

При необходимости мы можем комбинировать значения, разделяя их вертикальной чертой:

< TextView android: gravity=" bottom|right" android: layout_width=" match_parent" android: layout_height=" 200px" android: text=" Hello Android 7" android: background=" #e8eaf6" />

Layout_gravity

В отличие от gravity атрибут layout_gravity устанавливает позиционирование в контейнере. Он принимает те же значения, только позиционирование идет относительно внешнего контейнера:

· top: выравнивает элемент по верхней границе контейнера

· bottom: выравнивает элемент по нижней границе контейнера

· left: выравнивает элемент по левой границе контейнера

· right: выравнивает элемент по правой границе контейнера

· center_vertical: выравнивает элемент по центру по вертикали

· center_horizontal: выравнивает элемент по центру по горизонтали

· center: элемент позиционируется в центре

· fill_vertical: элемент растягивается по вертикали

· fill_horizontal: элемент растягивается по горизонтали

· fill: элемент заполняет все пространство контейнера

· clip_vertical: обрезает верхнюю и нижнюю границу элемента

· clip_horizontal: обрезает правую и левую границу элемента

· start: элемент позиционируется в начале (в верхнем левом углу) контейнера

· end: элемент позиционируется в конце контейнера (в верхнем правом углу)

Например:

< LinearLayout xmlns: android=" http: //schemas.android.com/apk/res/android"  android: layout_width=" match_parent" android: layout_height=" match_parent" android: orientation=" horizontal" >    < TextView       android: layout_gravity=" center"        android: layout_width=" match_parent"        android: layout_height=" 200px"        android: textSize=" 22sp"        android: text=" Hello Android 7"        android: background=" #e8eaf6" /> < /LinearLayout>

При этом надо учитывать, что layout_gravity применяется только к классу LinearLayout или к его классам-наследникам, например, FrameLayout. В RelativeLayout этот атрибут не окажет никакого влияния.

Также внутри LinearLayout стоит учитывать ориентацию контейнера. Например, при вертикальной ориентации все элементы будут представлять вертикальный стек, идущий сверху вниз. Поэтому значения, которые относятся к позиционированию элемента по вертикали (например, top или bottom) никак не будут влиять на элемент. Также при горизонтальнйо ориентации LinearLayout не окажут никакого влияния значения, которые позиционируют элемент по горизонтали, например, left и right.

Программная установка gravity и layout_gravity

Чтобы установить параметр gravity у элемента надо вызвать метод setGravity(). Для установки программно параметра layout_gravity надо задать поле gravity у объекта LinearLayout.LayoutParams:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package com.example.eugene.layoutapp;   import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.Gravity; import android.widget.LinearLayout; import android.widget.TextView;   public class MainActivity extends AppCompatActivity {   protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);   LinearLayout linearLayout = new LinearLayout(this); TextView textView = new TextView(this); textView.setText(" Hello Android 7" ); textView.setTextSize(22); textView.setBackgroundColor(0xffe8eaf6);   // установка gravity textView.setGravity(Gravity.CENTER);   // установка высоты и ширины LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams (LinearLayout.LayoutParams.MATCH_PARENT, 200); // установка layout_gravity layoutParams.gravity = Gravity.CENTER; textView.setLayoutParams(layoutParams);   linearLayout.addView(textView); setContentView(linearLayout); } }



TableLayout

Контейнер TableLayout структурирует элементы управления по столбцам и строкам. Определим в файле activity_main.xml элемент TableLayout, который будет включать две строки и два столбца:

< TableLayout xmlns: android=" http: //schemas.android.com/apk/res/android"

android: layout_

android: layout_height=" match_parent" >

< TableRow>

   < TextView

       android: layout_weight=" 0.5"

       android: text=" Логин"

       android: layout_width=" wrap_content"

       android: layout_height=" wrap_content" />

 

   < EditText

       android: layout_weight=" 1"

       android: layout_width=" match_parent"

       android: layout_height=" wrap_content" />

< /TableRow>

 

< TableRow>

   < TextView

       android: layout_weight=" 0.5"

       android: text=" Email"

       android: layout_width=" wrap_content"

       android: layout_height=" wrap_content" />

 

   < EditText

       android: layout_weight=" 1"

       android: layout_width=" wrap_content"

       android: layout_height=" wrap_content" />

< /TableRow>

< /TableLayout>

Используя элемент TableRow, мы создаем отдельную строку. Как разметка узнает сколько столбцов надо создать? Android находит строку с максимальным количеством виджетов одного уровня, и это количество будет означать количество столбцов. Например, в данном случае у нас определены две строки и в каждой по два элемента. Если бы в какой-нибудь из них было бы три виджета, то соответственно столбцов было бы также три, даже если в другой строке осталось бы два виджета.

Причем элемент TableRow наследуется от класса LinearLayout, поэтому мы можем к нему применять тот же функционал, что и к LinearLayout. В частности, для определения пространства для элементов в строке используется атрибут android: layout_weight.

Если какой-то элемент должен быть растянут на ряд столбцов, то мы можем растянуть его с помощью атрибута layout_span, который указывает на какое количество столбцов надо растянуть элемент:

< TableLayout xmlns: android=" http: //schemas.android.com/apk/res/android"

android: layout_width=" match_parent"

  android: layout_height=" match_parent" >

< TableRow>

   < TextView

       android: textSize=" 22sp"

       android: text=" Логин"

       android: layout_width=" 100dp"

       android: layout_height=" wrap_content" />

 

   < EditText

          android: textSize=" 22sp"

       android: layout_width=" 200dp"

       android: layout_height=" wrap_content" />

< /TableRow>

 

< TableRow>

   < TextView

       android: textSize=" 22sp"

       android: text=" Email"

       android: layout_width=" wrap_content"

       android: layout_height=" wrap_content" />

 

   < EditText

       android: textSize=" 22sp"

       android: layout_width=" wrap_content"

       android: layout_height=" wrap_content" />

< /TableRow>

< TableRow>

   < Button

       android: text=" Отправить"

       android: layout_width=" wrap_content"

       android: layout_height=" wrap_content"

       android: layout_span=" 2" />

< /TableRow>

< /TableLayout>

Также можно растянуть элемент на всю строку, установив у него атрибут android: layout_weight=" 1":

< TableRow>

< Button

   android: text=" Отправить"

   android: layout_width=" match_parent"

   android: layout_height=" wrap_content"

   android: layout_weight=" 1" />

< /TableRow>



FrameLayout

Контейнер FrameLayout предназначен для вывода на экран одного помещенного в него визуального элемента. Если же мы поместим несколько элементов, то они будут накладываться друг на друга.

Допустим, вложим в FrameLayout два элемента TextView:

<? xml version=" 1.0" encoding=" utf-8"? >

< FrameLayout xmlns: android=" http: //schemas.android.com/apk/res/android"

android: id=" @+id/activity_main"

android: layout_width=" match_parent"

android: layout_height=" match_parent" >

 

< TextView

   android: layout_width=" wrap_content"

   android: layout_height=" wrap_content"

   android: text=" Hello World! "

   android: textSize=" 26sp" />

< TextView

   android: layout_width=" wrap_content"

   android: layout_height=" wrap_content"

   android: text=" Android Nougat 7.1"

   android: textSize=" 26sp"

   android: layout_marginTop=" 50dp" />

 

< /FrameLayout>

Здесь оба элемента позиционируются в одно и то же место - в левый верхний угол контейнера FrameLayout, и чтобы избежать наложения, в данном случае у второго TextView устанавливается отступ сверху в 50 единиц.

Нередко FrameLayout применяется для создания производных контейнеров, например, ScrollView, который обеспечивает прокрутку.

Элементы управления, которые помещаются в FrameLayout, могут установить свое позиционирование с помощью атрибута android: layout_gravity:

<? xml version=" 1.0" encoding=" utf-8"? >

< FrameLayout xmlns: android=" http: //schemas.android.com/apk/res/android"

android: id=" @+id/activity_main"

android: layout_width=" match_parent"

android: layout_height=" match_parent" >

 

< TextView

   android: layout_width=" wrap_content"

   android: layout_height=" wrap_content"

   android: text=" Hello World! "

   android: textSize=" 26sp"

   android: layout_gravity=" center_horizontal" />

< TextView

   android: layout_width=" wrap_content"

   android: layout_height=" wrap_content"

   android: text=" Welcome to Android Nougat World"

   android: textSize=" 26sp"

   android: layout_gravity=" center" />

< TextView

   android: layout_width=" wrap_content"

   android: layout_height=" wrap_content"

   android: text=" Android Nougat 7.1"

   android: textSize=" 26sp"

   android: layout_gravity=" bottom|center_horizontal" />

 

< /FrameLayout>

При указании значения мы можем комбинировать ряд значений, разделяя их вертикальной чертой: bottom|center_horizontal

Программное создание FrameLayout в коде MainActivity:

package com.example.eugene.layoutapp;

 

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.Gravity;

import android.widget.FrameLayout;

import android.widget.TextView;

 

public class MainActivity extends AppCompatActivity {

 

@Override

protected void onCreate(Bundle savedInstanceState) {

      super.onCreate(savedInstanceState);

 

   FrameLayout frameLayout = new FrameLayout(this);

   TextView textView1 = new TextView(this);

   textView1.setText(" Hello World! " );

              

   FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams

           (FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);

   layoutParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;

              

   textView1.setLayoutParams(layoutParams);

   textView1.setTextSize(26);

   frameLayout.addView(textView1);

   setContentView(frameLayout);

}

}



GridLayout

GridLayout представляет еще один контейнер, который позволяет создавать табличные представления. GridLayout состоит из коллекции строк, каждая из которых состоит из отдельных ячеек:

< GridLayout xmlns: android=" http: //schemas.android.com/apk/res/android"

 android: layout_width=" match_parent"

android: layout_height=" match_parent"

android: rowCount=" 3"

android: columnCount=" 3" >

 

< Button android: text=" 1" />

< Button android: text=" 2" />

< Button android: text=" 3" />

< Button android: text=" 4" />

< Button android: text=" 5" />

< Button android: text=" 6" />

< Button android: text=" 7" />

 

< Button android: text=" 8" />

 

< Button android: text=" 9" />

< /GridLayout>

С помощью атрибутов android: rowCount и android: columnCount устанавливается число строк и столбцов соответственно. Так, в данном случае устанавливаем 3 строки и 3 столбца. GridLayout автоматически может позиционировать вложенные элементы управления по строкам. Так, в нашем случае первая кнопка попадает в первую ячейку (первая строка первый столбец), вторая кнопка - во вторую ячейку и так далее.

При этом ширина столбцов устанавливается автоматически по ширине самого широкого элемента.

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

  • android: layout_column: номер столбца (отсчет идет от нуля)
  • android: layout_row: номер строки
  • android: layout_columnSpan: количество столбцов, на которые растягивается элемент
  • android: layout_rowSpan: количество строк, на которые растягивается элемент

Например:

< GridLayout xmlns: android=" http: //schemas.android.com/apk/res/android"

android: layout_width=" match_parent"

android: layout_height=" match_parent"

android: orientation=" horizontal"

android: rowCount=" 3"

android: columnCount=" 3" >

 

< Button

   android: text=" 1"

   android: layout_column=" 0"

   android: layout_row=" 0" />

< Button android: text=" 2"

   android: layout_column=" 1"

   android: layout_row=" 0" />

< Button android: text=" 3"

   android: layout_column=" 2"

   android: layout_row=" 0" />

< Button android: text=" 4"

   android: layout_width=" 180dp"

   android: layout_columnSpan=" 2" />

< Button android: text=" 5"

   android: layout_height=" 100dp"

   android: layout_rowSpan=" 2" />

< Button android: text=" 6" />

< Button android: text=" 7" />

< /GridLayout>



ConstraintLayout

ConstraintLayout представляет новый тип контейнеров, который является развитием RelativeLayout и позволяет создавать гибкие и масштабируемые интерфейсы.

Начиная с версии Android Studio 2.3 ConstraintLayout был добавлен в список стандартных компонентов и даже является контейнером, который используется в файлах layout по умолчанию. Однако если вы используете Android Studio 2.2 или ниже, то в этом случае функциональность ConstraintLayout надо дополнительно добавлять.

Рассмотрим добавление ConstraintLayout для Android Studio до версии 2.3 (если у вас версия 2.3 и выше, то ничего добавлять не надо). Для этого перейдем в проекте к файлу build.gradle, который относится к модулю проекта, а не ко всему проекту:

В этом файле есть узел Dependencies примерно следующего содержания:

dependencies {

compile fileTree(dir: 'libs', include: ['*.jar'])

androidTestCompile('com.android.support.test.espresso: espresso-core: 2.2.2', {

   exclude group: 'com.android.support', module: 'support-annotations'

})

compile 'com.android.support: appcompat-v7: 25.1.0'

testCompile 'junit: junit: 4.12'

}

Добавим в конец этого узла строку:

dependencies {

// остальное содержимое

compile 'com.android.support.constraint: constraint-layout: 1.0.2'

}

В данном случае мы добавляем пакет версии " 1.0.2", но естественно версия может отличаться.

После сохранения файла в Android Studio отобразится сообщение с ссылкой " Sync Now". Нажмем на эту ссылку для синхронизации проекта с файлом build.gradle:

Для позиционирования элемента внутри ConstraintLayout необходимо указать ограничения (constraints). Есть несколько типов ограничений. В частности, для установки позиции относительно определенного элемента испльзуются следующие ограничения:

  • layout_constraintLeft_toLeftOf: левая граница позиционируется относительно левой границы другого элемента
  • layout_constraintLeft_toRightOf: левая граница позиционируется относительно правой границы другого элемента
  • layout_constraintRight_toLeftOf: правая граница позиционируется относительно левой границы другого элемента
  • layout_constraintRight_toRightOf: правая граница позиционируется относительно правой границы другого элемента
  • layout_constraintTop_toTopOf: верхняя граница позиционируется относительно верхней границы другого элемента
  • layout_constraintBottom_toBottomOf: нижняя граница позиционируется относительно нижней границы другого элемента
  • layout_constraintBaseline_toBaselineOf: базовая линия позиционируется относительно базовой линии другого элемента
  • layout_constraintTop_toBottomOf: верхняя граница позиционируется относительно нижней границы другого элемента
  • layout_constraintBottom_toTopOf: нижняя граница позиционируется относительно верхней границы другого элемента
  • layout_constraintStart_toEndOf: аналог layout_constraintLeft_toRightOf
  • layout_constraintStart_toStartOf: аналог layout_constraintLeft_toLeftOf
  • layout_constraintEnd_toStartOf: аналог layout_constraintRight_toLeftOf
  • layout_constraintEnd_toEndOf: аналог layout_constraintRight_toRightOf

Позиционирования может производиться относительно границ самого контейнера ContentLayout (в этом случае ограничение имеет значение " parent" ), либо же относительно любого другого элемента внутри ConstraintLayout, тогда в качестве значения ограничения указывается id этого элемента.

Чтобы указать отступы от элемента, относительно которого производится позиционирования, применяются следующие атрибуты:

  • android: layout_marginLeft: отступ от левой границы
  • android: layout_marginRight: отступ от правой границы
  • android: layout_marginTop: отступ от верхней границы
  • android: layout_marginBottom: отступ от нижней границы
  • android: layout_marginStart: отступ от левой границы
  • android: layout_marginEnd: отступ от правой границы

Рассмотрим на простом примере. Изменим файл разметки интерфейса activity_main:

<? xml version=" 1.0" encoding=" utf-8"? >

< android.support.constraint.ConstraintLayout

xmlns: android=" http: //schemas.android.com/apk/res/android"

xmlns: app=" http: //schemas.android.com/apk/res-auto"

android: id=" @+id/activity_main"

android: layout_width=" match_parent"

android: layout_height=" match_parent" >

< TextView

   android: layout_width=" wrap_content"

   android: layout_height=" wrap_content"

   android: text=" Hello Android"

 

   app: layout_constraintTop_toTopOf=" parent"

   android: layout_marginTop=" 30dp"

 

   android: layout_marginLeft=" 80dp"

   app: layout_constraintLeft_toLeftOf=" parent" />

              

< /android.support.constraint.ConstraintLayout>

Здесь устанавливаются два ограничения относительно родительского контейнера ConstraintLayout, поэтому ограничения имеют значение parent. Поэтому все отступы, которые определены у элемента TextView, устанавливаются относительно верхнего и левого края контейнера:

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

Рассмотрим более сложный пример:

<? xml version=" 1.0" encoding=" utf-8"? >

< android.support.constraint.ConstraintLayout

xmlns: android=" http: //schemas.android.com/apk/res/android"

xmlns: app=" http: //schemas.android.com/apk/res-auto"

xmlns: tools=" http: //schemas.android.com/tools"

android: id=" @+id/activity_main"

android: layout_width=" match_parent"

android: layout_height=" match_parent" >

< ImageView

   android: text=" TextView"

   android: background=" #3F51B5"

   android: layout_width=" 50dp"

   android: layout_height=" 50dp"

   android: id=" @+id/imageView"

 

   app: layout_constraintLeft_toLeftOf=" parent"

   android: layout_marginLeft=" 16dp"

 

   app: layout_constraintTop_toTopOf=" parent"

   android: layout_marginTop=" 16dp" />

 

< TextView

   android: layout_width=" 0dp"

   android: layout_height=" 0dp"

   android: textSize=" 20sp"

   android: id=" @+id/textView"

   android: text=" Lorem Ipsum is simply dummy text of the printing and typesetting industry... remaining essentially unchanged"

 

   app: layout_constraintLeft_toRightOf=" @+id/imageView"

   android: layout_marginLeft=" 16dp"

 

   app: layout_constraintTop_toBottomOf=" @+id/imageView"

   android: layout_marginTop=" 16dp"

 

   app: layout_constraintRight_toRightOf=" parent"

   android: layout_marginRight=" 16dp"

 

   app: layout_constraintBottom_toTopOf=" @+id/button2"

   android: layout_marginBottom=" 16dp" />

 

< Button

   android: text=" Cancel"

   android: layout_width=" 93dp"

   android: layout_height=" 53dp"

   android: id=" @+id/button1"

       

   app: layout_constraintRight_toRightOf=" parent"

   android: layout_marginRight=" 16dp"

       

   app: layout_constraintBottom_toBottomOf=" parent"

   android: layout_marginBottom=" 16dp" />

 

< Button

   android: text=" OK"

   android: layout_width=" 93dp"

   android: layout_height=" 53dp"

   android: id=" @+id/button2"

       

   app: layout_constraintRight_toLeftOf=" @+id/button1"

   android: layout_marginRight=" 16dp"

   app: layout_constraintBaseline_toBaselineOf=" @+id/button1" />

< /android.support.constraint.ConstraintLayout>

Во-первых, здесь элемент позиционируется относительно контейнера ConstraintLayout: от верхней и левой границы контейнера до соответствующих границ ImageView по 16 dip.

Во-вторых, относительно контейнера позиционируется также кнопка с id=button1: от правой и нижней границы контейнера до соответствующих границ Button также по 16 dip.

В-третьих, вторая кнопка с id=button2 позиционируется относительно первой кнопки: от правой границы второй кнопки до левой границы первой кнопки (app: layout_constraintRight_toLeftOf=" @+id/button1" ) также 16 dip. И чтобы обе кнопки находились на одном уровне, у них идет выравнивание по базовой линии: app: layout_constraintBaseline_toBaselineOf=" @+id/button1".

И элемент TextView с куском текста позиционируется сразу относительно контейнера, элемента ImageView и второй кнопки.

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



ScrollView

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

Например, определим ряд TextView с большими текстами:

< ScrollView

xmlns: android=" http: //schemas.android.com/apk/res/android"

android: id=" @+id/activity_main"

android: layout_width=" match_parent"

android: layout_height=" match_parent" >

< LinearLayout

     android: layout_width=" match_parent"

   android: layout_height=" match_parent"

   android: orientation=" vertical"

   >

   < TextView

       android: layout_width=" wrap_content"

       android: layout_height=" wrap_content"

      android: text=" What is Lorem Ipsum? "

       android: textSize=" 34sp" />

   < TextView

       android: layout_width=" wrap_content"

       android: layout_height=" wrap_content"

       android: text=" Lorem Ipsum is simply dummy text of the printing and typesetting industry...like Aldus PageMaker including versions of Lorem Ipsum."

    android: textSize=" 14sp" />

   < TextView

       android: layout_width=" wrap_content"

       android: layout_height=" wrap_content"

       android: text=" Why do we use it? "

       android: layout_marginTop=" 16dp"

       android: textSize=" 34sp" />

   < TextView

       android: layout_width=" wrap_content"

       android: layout_height=" wrap_content"

       android: text=" Lorem Ipsum is simply dummy text of the printing and typesetting industry...like Aldus PageMaker including versions of Lorem Ipsum."

       android: textSize=" 14sp" />

   < TextView

       android: layout_width=" wrap_content"

       android: layout_height=" wrap_content"

       android: text=" Where can I get some? "

       android: layout_marginTop=" 16dp"

       android: textSize=" 34sp" />

   < TextView

       android: layout_width=" wrap_content"

       android: layout_height=" wrap_content"

       android: text=" There are many variations of passages of Lorem Ipsum available... or non-characteristic words etc."

       android: textSize=" 14sp" />

< /LinearLayout>

< /ScrollView>

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

Создание ScrollView программно в коде MainActivity:

package com.example.eugene.layoutapp;

 

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.ViewGroup;

import android.widget.ScrollView;

import android.widget.TextView;

 

public class MainActivity extends AppCompatActivity {

 

@Override

protected void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState);

 

   ScrollView scrollView = new ScrollView(this);

 

   TextView textView1 = new TextView(this);

   textView1.setText(" Lorem Ipsum is simply dummy text of the printing and typesetting industry...like Aldus PageMaker including versions of Lorem Ipsum." );

   textView1.setLayoutParams(new ViewGroup.LayoutParams

           (ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));

   textView1.setTextSize(26);

   scrollView.addView(textView1);

   setContentView(scrollView);

}

}



Вложенные layout

Одна layout может содержать другую layout. Для этого применяется элемент include.

Например, добавим в папку res/layout два файла layout, которые пусть будут называться text_panel.xml и button_panel.xml:

В файле text_panel.xml определим следующий код:

<? xml version=" 1.0" encoding=" utf-8"? >

< LinearLayout

xmlns: android=" http: //schemas.android.com/apk/res/android"

android: layout_width=" wrap_content"

android: layout_height=" wrap_content" >

< TextView

   android: id=" @+id/clicksText"

   android: layout_width=" wrap_content"

   android: layout_height=" wrap_content"

   android: textSize=" 20sp"

   android: text=" 0 Clicks" />

< /LinearLayout>

По сути здесь просто определено поле TextView для вывода текста.

В файле button_panel.xml определим следующую разметку:

<? xml version=" 1.0" encoding=" utf-8"? >

< LinearLayout

xmlns: android=" http: //schemas.android.com/apk/res/android"

android: layout_width=" wrap_content"

android: layout_height=" wrap_content" >

< Button

android: layout_width=" wrap_content"

android: layout_height=" wrap_content"

android: text=" Click"

android: onClick=" onClick" />

< /LinearLayout>

Здесь определена кнопка, нажатия которой мы будем обрабатывать.

Основным файлом разметки, который определяет интерфейс приложения, по-прежнему является activity_main.xml. Изменим его:

<? xml version=" 1.0" encoding=" utf-8"? >

< LinearLayout

xmlns: android=" http: //schemas.android.com/apk/res/android"

android: layout_width=" match_parent"

android: layout_height=" match_parent"

android: orientation=" vertical"

android: padding=" 16dp" >

 

< include layout=" @layout/text_panel" />

< include layout=" @layout/button_panel" />

 

< /LinearLayout>

С помощью LinearLayout весь интерфейс здесь организуется в виде вертикального стека. С помощью элементов include внутрь LinearLayout добавляется содержимое файлов text_panel.xml и button_panel.xml. Для указания названия файла применяется атрибут layout.

Это все равно, что если бы мы напрямую вместо элемента include добавили содержимое файлов. Однако такой способ имеет свои преимущества. Например, какая-то часть разметки, группа элементов управления может повторяться в различных activity. И чтобы не определять по сто раз эти элементы, можно вынести их в отдельный файл layout и с помощью include подключать их.

Также изменим код MainActivity:

package com.example.eugene.viewsapplication;

 

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.TextView;

 

public class MainActivity extends AppCompatActivity {

 

int clicks = 0;

@Override

protected void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState);

   setContentView(R.layout.activity_main);

}

 

public void onClick(View view){

   TextView clicksText = findViewById(R.id.clicksText);

   clicks++;

   clicksText.setText(clicks + " Clicks" );

}

}

В MainActivity мы можем обращаться к элементам во вложенных файлах layout. Например, мы можем установить обработчик нажатия кнопки, в котором при нажатии изменять текст в TextView.

При этом мы несколько раз можем добавлять в один файл layout другой файл layout. Для этого вначале изменим файл button_panel.xml следующим образом:

<? xml version=" 1.0" encoding=" utf-8"? >

< LinearLayout

xmlns: android=" http: //schemas.android.com/apk/res/android"

android: layout_width=" wrap_content"

android: layout_height=" wrap_content"

android: background=" #3F51B5"

android: paddingTop=" 10dp"

android: paddingBottom=" 10dp" >

< Button

android: id=" @+id/clickBtn"

android: layout_width=" wrap_content"

android: layout_height=" wrap_content"

android: text=" Clicks" />

< /LinearLayout>

И изменим файл activity_main.xml:

<? xml version=" 1.0" encoding=" utf-8"? >

< RelativeLayout

xmlns: android=" http: //schemas.android.com/apk/res/android"

android: layout_width=" match_parent"

android: layout_height=" match_parent"

android: padding=" 16dp" >

 

< include layout=" @layout/text_panel" />

   

< include layout=" @layout/button_panel"

   android: id=" @+id/top_button_panel"

   android: layout_width=" match_parent"

   android: layout_height=" wrap_content"

   android: layout_above=" @id/bottom_button_panel" />

< include layout=" @layout/button_panel"

   android: id=" @+id/bottom_button_panel"

   android: layout_width=" match_parent"

   android: layout_height=" wrap_content"

   android: layout_alignParentBottom=" true"

   android: layout_marginBottom=" 10dp"

   android: layout_marginTop=" 10dp" />

 

< /RelativeLayout>

Теперь элементы размещены в RelativeLayout, причем файл button_panel.xml добавляется два раза. Важно, что при добавлении этого файла каждому элементу include присвоен определенный id. По этому id мы сможем узнать, о каком именно элементе include идет речь.

Также изменим MainActivity:

package com.example.eugene.viewsapplication;

 

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

import android.widget.TextView;

 

public class MainActivity extends AppCompatActivity {

 

int clicks = 0;

@Override

protected void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState);

   setContentView(R.layout.activity_main);

 

   View topButtonPanel = findViewById(R.id.top_button_panel);

   View bottomButtonPanel = findViewById(R.id.bottom_button_panel);

   final TextView clicksText = findViewById(R.id.clicksText);

 

   Button topButton = topButtonPanel.findViewById(R.id.clickBtn);

   Button bottomButton = bottomButtonPanel.findViewById(R.id.clickBtn);

 

   topButton.setText(" +" );

   bottomButton.setText(" -" );

 

   topButton.setOnClickListener(new View.OnClickListener() {

       @Override

       public void onClick(View v) {

           clicks++;

           clicksText.setText(clicks + " Clicks" );

       }

   });

   bottomButton.setOnClickListener(new View.OnClickListener() {

       @Override

       public void onClick(View v) {

           clicks--;

           clicksText.setText(clicks + " Clicks" );

       }

   });

}

}

Здесь вначале мы получаем отдельные элементы include по id. Затем в рамках этих элементов получаем кнопку. После этого мы можем установить у кнопко любой текст и повесить обработчик события нажатия. И таким образом, поведение обеих кнопок будет различаться.


Основные элементы управления.

TextView

Для простого вывода текста на экран предназначен элемент TextView. Он просто отображает текст без возможности его редактирования. Некоторые его основные атрибуты:

  • android: text: устанавливает текст элемента
  • android: textSize: устанавливает высоту текста, в качестве единиц измерения для указания высоты используются sp
  • android: background: задает фоновый цвет элемента в виде цвета в шестнадцатиричной записи или в виде цветового ресурса
  • android: textColor: задает цвет текста
  • android: textAllCaps: при значении true делает все символы в тексте заглавными
  • android: textDirection: устанавливает направление текста. По умолчанию используется направление слева направо, но с помощью значения rtl можно установить направление справо налево
  • android: textAlignment: задает выравнивание текста. Может принимать следующие значения:
    • center: выравнивание по центру
    • textStart: по левому краю
    • textEnd: по правому краю
    • viewStart: по левому краю
    • viewEnd: по правому краю
  • android: fontFamily: устанавливает тип шрифта. Может принимать следующие значения:
    • monospace
    • serif
    • serif-monospace
    • sans-serif
    • sans-serif-condensed
    • sans-serif-smallcaps
    • sans-serif-light
    • casual
    • cursive
    • cursive

Например, определим три текстовых поля:

<? xml version=" 1.0" encoding=" utf-8"? >

< LinearLayout xmlns: android=" http: //schemas.android.com/apk/res/android"

android: id=" @+id/activity_main"

android: orientation=" vertical"

android: layout_width=" match_parent"

android: layout_height=" match_parent" >

 

< TextView

   android: layout_height=" wrap_content"

   android: layout_width=" match_parent"

   android: layout_margin=" 10dp"

 

   android: text=" Hello Android 7"

          android: fontFamily=" sans-serif"

   android: textSize=" 26sp"

   android: background=" #ffebee"

   android: textColor=" #f44336" />

 < TextView

   android: layout_height=" wrap_content"

   android: layout_width=" match_parent"

   android: layout_margin=" 10dp"

 

   android: text=" Android Nougat"

   android: textAllCaps=" true"

   android: textSize=" 26sp"

   android: background=" #ede7f6"

   android: textColor=" #7e57c2" />

 

< TextView

   android: layout_height=" wrap_content"

   android: layout_width=" match_parent"

   android: layout_margin=" 10dp"

 

   android: text=" Hello Android 7"

   android: textAlignment=" textEnd"

   android: textSize=" 26sp"

   android: background=" #e8eaf6"

   android: textColor=" #5c6bc0" />

< /LinearLayout>

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

package com.example.eugene.layoutapp;

 

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.ViewGroup;

import android.widget.LinearLayout;

import android.widget.TextView;

import android.graphics.Typeface;

 

public class MainActivity extends AppCompatActivity {

 

@Override

protected void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState);

 

   LinearLayout linearLayout = new LinearLayout(this);

   TextView textView1 = new TextView(this);

   // установка фонового цвета

   textView1.setBackgroundColor(0xffe8eaf6);

   // установка цвета текста

   textView1.setTextColor(0xff5c6bc0);

   // делаем все буквы заглавными

   textView1.setAllCaps(true);

   // устанавливаем вравнивание текста по центру

   textView1.setTextAlignment(TextView.TEXT_ALIGNMENT_CENTER);

   // устанавливаем текста

   textView1.setText(" Android Nougat 7" );

            // установка шрифта

            textView1.setTypeface(Typeface.create(" casual", Typeface.NORMAL));

   // устанавливаем высоту текста

   textView1.setTextSize(26);

 

   LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams

           (ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);

      // установка внешних отступов

   layoutParams.setMargins(20, 20, 20, 20);

   // устанавливаем размеры

   textView1.setLayoutParams(layoutParams);

   linearLayout.addView(textView1);

   setContentView(linearLayout);

}

}

Иногда необходимо вывести на экран какую-нибудь ссылку, либо телефон, по нажатию на которые производилось бы определенное действие. Для этого в TextView определен атрибут android: autoLink:

< TextView android: id=" @+id/display_message"

android: text=" Посетите сайт https: //metanit.com"

android: textSize=" 21sp"

android: layout_width=" wrap_content"

android: layout_height=" wrap_content"

android: autoLink=" web|email" />

android: autoLink может принимать несколько значений:

  • none: отключает все ссылки
  • web: включает все веб-ссылки
  • email: включает ссылки на электронные адреса
  • phone: включает ссылки на номера телефонов
  • map: включает ссылки на карту
  • all: включает все вышеперечисленные ссылки

То есть при настройке android: autoLink=" web" если в тексте есть упоминание адреса url, то этот адрес будет выделяться, а при нажатии на него будет осуществлен переход к веб-браузеру, который откроет страницу по этому адресу. С помощью прямой черты мы можем объединять условия, как в данном случае: android: autoLink=" web|email"



EditText

Элемент EditText является подклассом класса TextView. Он также представляет текстовое поле, но теперь уже с возможностью ввода и редактирования текста. Таким образом, в EditText мы можем использовать все те же возможности, что и в TextView.

Из тех атрибутов, что не рассматривались в теме про TextView, следует отметить атрибут android: hint. Он позволяет задать текст, который будет отображаться в качестве подсказки, если элемент EditText пуст. Кроме того, мы можем использовать атрибут android: inputType, который позволяет задать клавиатуру для ввода. В частности, среди его значений можно выделить следующие:

  • text: обычная клавиатура для ввода однострочного текста
  • textMultiLine: многострочное текстовое поле
  • textEmailAddress: обычная клавиатура, на которой присутствует символ @, ориентирована на ввод email
  • textUri: обычная клавиатура, на которой присутствует символ /, ориентирована на ввод интернет-адресов
  • textPassword: клавиатура для ввода пароля
  • textCapWords: при вводе первый введенный символ слова представляет заглавную букву, остальные - строчные
  • number: числовая клавиатура
  • phone: клавиатура в стиле обычного телефона
  • date: клавиатура для ввода даты
  • time: клавиатура для ввода времени
  • datetime: клавиатура для ввода даты и времени

Используем EditText:

< LinearLayout

xmlns: android=" http: //schemas.android.com/apk/res/android"

android: id=" @+id/activity_main"

android: layout_width=" match_parent"

android: layout_height=" match_parent"

android: orientation=" vertical"

android: padding=" 16dp" >

 

< EditText

   android: layout_width=" match_parent"

   android: layout_height=" wrap_content"

   android: hint=" Введите имя" />

< EditText

   android: layout_marginTop=" 16dp"

   android: layout_width=" match_parent"

   android: layout_height=" match_parent"

   android: hint=" Введите сообщение"

   android: inputType=" textMultiLine"

   android: gravity=" top" />

< /LinearLayout>

Первое поле здесь обычное однострочное, а второе - многострочное. Чтобы во втором поле текст выравнивался по верху, дополнительно устанавливается атрибут android: gravity=" top".

Одной из возможностей элемента EditText также является возможность обработать введенные символы по мере ввода пользователя. Для этого определим в файле activity_main.xml следующую разметку:

< LinearLayout

xmlns: android=" http: //schemas.android.com/apk/res/android"

android: id=" @+id/activity_main"

android: layout_width=" match_parent"

android: layout_height=" match_parent"

android: orientation=" vertical"

android: padding=" 16dp" >

 

< TextView

   android: id=" @+id/textView"

   android: textSize=" 34sp"

   android: layout_width=" match_parent"

   android: layout_height=" wrap_content" />

< EditText

   android: layout_width=" match_parent"

   android: layout_height=" wrap_content"

   android: hint=" Введите имя"

   android: id=" @+id/editText" />

   

< /LinearLayout>

Предполагается, что введенные в EditText символы тут же будут отображаться в элементе TextView. И для этого также изменим код MainActivity:

package com.example.eugene.layoutapp;

 

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.text.Editable;

import android.text.TextWatcher;

import android.widget.EditText;

import android.widget.TextView;

 

public class MainActivity extends AppCompatActivity {

 

 @Override

protected void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState);

 

   setContentView(R.layout.activity_main);

 

   EditText editText = (EditText) findViewById(R.id.editText);

       

          editText.addTextChangedListener(new TextWatcher() {

 

       public void afterTextChanged(Editable s) {}

 

       public void beforeTextChanged(CharSequence s, int start,

                                     int count, int after) {

       }

 

       public void onTextChanged(CharSequence s, int start,

                                 int before, int count) {

           TextView textView = (TextView) findViewById(R.id.textView);

           textView.setText(s);

       }

   });

}

}

С помощью метода addTextChangedListener() здесь к элементу EditText добавляется слушатель ввода текста - объект TextWatcher. Для его использования нам надо реализовать три метода, но в реалности нам хватит реализации метода onTextChanged, который вызывается при изменении текста. Введенный текст передается в этот метод в качестве параметра CharSequence. В самом методе просто передаем этот текст в элемент TextView.

В итоге при вводе в EditText все символы также будут отображаться в TextView:



Button

Одним из часто используемых элементов являются кнопки, которые представлены классом android.widget.Button. Ключевой особенностью кнопок является возможность взаимодействия с пользователем через нажатия.

Некоторые ключевые атрибуты, которые можно задать у кнопок:

  • text: задает текст на кнопке
  • textColor: задает цвет текста на кнопке
  • background: задает фоновый цвет кнопки
  • textAllCaps: при значении true устанавливает текст в верхнем регистре. По умолчанию как раз и применяется значение true
  • onClick: задает обработчик нажатия кнопки

Итак, изменим код в activity_main.xml следующим образом:

< LinearLayout

xmlns: android=" http: //schemas.android.com/apk/res/android"

android: id=" @+id/activity_main"

android: layout_width=" match_parent"

android: layout_height=" match_parent"

android: orientation=" vertical"

android: padding=" 16dp" >

 

< TextView

   android: id=" @+id/textView"

   android: textSize=" 34sp"

   android: layout_width=" match_parent"

   android: layout_height=" wrap_content" />

  < EditText

   android: layout_width=" match_parent"

   android: layout_height=" wrap_content"

   android: hint=" Введите имя"

   android: id=" @+id/editText" />

< Button

   android: layout_width=" wrap_content"

   android: layout_height=" wrap_content"

   android: text=" Click"

   android: onClick=" sendMessage" />

 

< /LinearLayout>

При помощью атрибута android: onClick можно задать метод в коде java, который будет обрабатывать нажатия кнопки. Так, в вышеприведенном примере это метод sendMessage. Теперь перейдем к коду MainActivity и пропишем в нем такой метод:

package com.example.eugene.layoutapp;

 

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.EditText;

import android.widget.TextView;

 

public class MainActivity extends AppCompatActivity {

 

@Override

protected void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState);

   setContentView(R.layout.activity_main);

}

// Обработка нажатия кнопки

public void sendMessage(View view) {

   TextView textView = (TextView) findViewById(R.id.textView);

   EditText editText = (EditText) findViewById(R.id.editText);

   textView.setText(" Добро пожаловать, " + editText.getText());

}

}

При создании метода обработки нажатия следует учитывать следующие моменты:

  • Метод должен объявляться с модификатором public
  • Должен возвращать значение void
  • В качестве параметра принимать объект View. Этот объект View и представляет собой нажатую кнопку

В данном случае после нажатия на кнопку в TextView выводится текст из EditText.

Аналогичный пример полностью в коде MainActivity:

package com.example.eugene.layoutapp;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

import android.widget.LinearLayout;

import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

EditText editText;

TextView textView;

@Override

protected void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState);

   LinearLayout linearLayout = new LinearLayout(this);

   linearLayout.setOrientation(LinearLayout.VERTICAL);

   textView = new TextView(this);

   textView.setLayoutParams(new LinearLayout.LayoutParams(

           LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT

   ));

   linearLayout.addView(textView);

 

   editText = new EditText(this);

   editText.setHint(" Введите имя" );

   editText.setLayoutParams(new LinearLayout.LayoutParams(

           LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT

   ));

   linearLayout.addView(editText);

 

   Button button = new Button(this);

   button.setText(" CLICK" );

   button.setLayoutParams(new LinearLayout.LayoutParams(

           LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT

   ));

   linearLayout.addView(button);

 

      button.setOnClickListener(new View.OnClickListener() {

       public void onClick(View v) {

           // Обработка нажатия

           textView.setText(" Добро пожаловать, " + editText.getText());

       }

   });

 

   setContentView(linearLayout);

}

}

При программном создании кнопки мы можем определить у нее слушатель нажатия View.OnClickListener и с помощью его метода onClick также обработать нажатие:

button.setOnClickListener(new View.OnClickListener() {

public void onClick(View v) {

   // Обработка нажатия

}

});



Приложение Калькулятор

Зная некоторые основы компоновки и такие элементы как TextView, EditText и Button, уже можно составить более менее полноценное приложение. В данном случае мы сделаем простенький калькулятор.

Для этого создадим новый проект и определим в файле activity_main.xml следующий интерфейс:

<? xml version=" 1.0" encoding=" utf-8"? >

< LinearLayout xmlns: android=" http: //schemas.android.com/apk/res/android"

android: id=" @+id/activity_main"

android: layout_width=" match_parent"

android: layout_height=" match_parent"

android: orientation=" vertical"

android: padding=" 16dp" >

< LinearLayout

   android: id=" @+id/result"

   android: layout_width=" match_parent"

   android: layout_height=" wrap_content" >

 

   < TextView

       android: id=" @+id/resultField"

       android: layout_width=" 0dp"

       android: layout_weight=" 1"

       android: textSize=" 18sp"

       android: layout_height=" wrap_content" />

   < TextView

       android: id=" @+id/operationField"

       android: layout_width=" 0dp"

       android: layout_weight=" 1"

       android: textSize=" 18sp"

       android: layout_height=" wrap_content"

       />

< /LinearLayout>

< EditText

   android: id=" @+id/numberField"

   android: layout_width=" match_parent"

   android: layout_height=" wrap_content"

   android: inputType=" phone" />

< LinearLayout

   android: layout_width=" match_parent"

   android: layout_height=" wrap_content"

   android: layout_marginTop=" 16dp" >

   < Button

       android: layout_weight=" 1"

       android: layout_width=" 0dp"

       android: layout_height=" wrap_content"

       android: text=" 7"

       android: onClick=" onNumberClick" />

   < Button

       android: layout_weight=" 1"

       android: layout_width=" 0dp"

       android: layout_height=" wrap_content"

       android: text=" 8"

       android: onClick=" onNumberClick" />

   < Button

       android: layout_weight=" 1"

       android: layout_width=" 0dp"

       android: layout_height=" wrap_content"

       android: text=" 9"

       android: onClick=" onNumberClick" />

   < Button

       android: layout_weight=" 1"

       android: layout_width=" 0dp"

       android: layout_height=" wrap_content"

       android: text=" /"

       android: onClick=" onOperationClick" />

< /LinearLayout>

< LinearLayout

   android: layout_width=" match_parent"

   android: layout_height=" wrap_content" >

   < Button

       android: layout_weight=" 1"

       android: layout_width=" 0dp"

       android: layout_height=" wrap_content"

       android: text=" 4"

       android: onClick=" onNumberClick" />

   < Button

       android: layout_weight=" 1"

       android: layout_width=" 0dp"

       android: layout_height=" wrap_content"

       android: text=" 5"

       android: onClick=" onNumberClick" />

   < Button

       android: layout_weight=" 1"

       android: layout_width=" 0dp"

       android: layout_height=" wrap_content"

       android: text=" 6"

       android: onClick=" onNumberClick" />

   < Button

       android: layout_weight=" 1"

       android: layout_width=" 0dp"

       android: layout_height=" wrap_content"

       android: text=" *"

       android: onClick=" onOperationClick" />

< /LinearLayout>

< LinearLayout

   android: layout_width=" match_parent"

   android: layout_height=" wrap_content" >

   < Button

       android: layout_weight=" 1"

       android: layout_width=" 0dp"

        android: layout_height=" wrap_content"

       android: text=" 1"

       android: onClick=" onNumberClick" />

   < Button

       android: layout_weight=" 1"

       android: layout_width=" 0dp"

       android: layout_height=" wrap_content"

       android: text=" 2"

       android: onClick=" onNumberClick" />

   < Button

       android: layout_weight=" 1"

       android: layout_width=" 0dp"

       android: layout_height=" wrap_content"

       android: text=" 3"

        android: onClick=" onNumberClick" />

   < Button

       android: layout_weight=" 1"

       android: layout_width=" 0dp"

       android: layout_height=" wrap_content"

       android: text=" -"

       android: onClick=" onOperationClick" />

< /LinearLayout>

< LinearLayout

   android: layout_width=" match_parent"

   android: layout_height=" wrap_content" >

   < Button

       android: layout_weight=" 1"

       android: layout_width=" 0dp"

       android: layout_height=" wrap_content"

       android: text=" 0"

       android: onClick=" onNumberClick" />

   < Button

       android: layout_weight=" 1"

       android: layout_width=" 0dp"

       android: layout_height=" wrap_content"

       android: text=", "

       android: onClick=" onNumberClick" />

   < Button

       android: layout_weight=" 1"

       android: layout_width=" 0dp"

       android: layout_height=" wrap_content"

       android: text=" +"

       android: onClick=" onOperationClick" />

   < Button

       android: layout_weight=" 1"

       android: layout_width=" 0dp"

       android: layout_height=" wrap_content"

       android: text=" ="

       android: onClick=" onOperationClick" />

< /LinearLayout>

< /LinearLayout>

В итоге весь интерфейс будет выглядеть следующим образом:

Корневой контейнер компоновки представляет элемент LinearLayout с вертикальной ориентацией. Первый элементв нем - горизонтальный элемент LinearLayout, в котором определены два текстовых поля TextView: одно для вывода результата вычислений и одно для вывода текущего знака операции.

Затем идет элемент EditText, предназначенный для ввода чисел.

И далее расположены четыре элемента LinearLayout с горизонтальными рядами кнопок. Чтобы все кнопки занимали равное пространство внутри контейнера, для них установлены атрибуты android: layout_weight=" 1" и android: layout_width=" 0dp".

Кроме того, для числовых кнопок в качестве обработчика нажатия установлен метод onNumberClick, а для кнопок со знаками операций атрибут onClick указывает на метод onOperationClick.

Теперь изменим класс MainActivity:

package com.example.eugene.calculator;

 

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

import android.widget.TextView;

 

public class MainActivity extends AppCompatActivity {

 

TextView resultField; // текстовое поле для вывода результата

EditText numberField; // поле для ввода числа

TextView operationField;   // текстовое поле для вывода знака операции

Double operand = null; // операнд операции

String lastOperation = " ="; // последняя операция

 

@Override

protected void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState);

   setContentView(R.layout.activity_main);

            // получаем все поля по id из activity_main.xml

   resultField =(TextView) findViewById(R.id.resultField);

   numberField = (EditText) findViewById(R.id.numberField);

   operationField = (TextView) findViewById(R.id.operationField);

}

    // сохранение состояния

@Override

protected void onSaveInstanceState(Bundle outState) {

   outState.putString(" OPERATION", lastOperation);

   if(operand! =null)

       outState.putDouble(" OPERAND", operand);

   super.onSaveInstanceState(outState);

}

    // получение ранее сохраненного состояния

@Override

protected void onRestoreInstanceState(Bundle savedInstanceState) {

   super.onRestoreInstanceState(savedInstanceState);

   lastOperation = savedInstanceState.getString(" OPERATION" );

   operand= savedInstanceState.getDouble(" OPERAND" );

   resultField.setText(operand.toString());

   operationField.setText(lastOperation);

}

    // обработка нажатия на числовую кнопку

public void onNumberClick(View view){

 

   Button button = (Button)view;

   numberField.append(button.getText());

 

   if(lastOperation.equals(" =" ) & & operand! =null){

       operand = null;

   }

}

    // обработка нажатия на кнопку операции

public void onOperationClick(View view){

 

   Button button = (Button)view;

   String op = button.getText().toString();

   String number = numberField.getText().toString();

            // если введенно что-нибудь

   if(number.length()> 0){

       number = number.replace(', ', '.');

       try{

           performOperation(Double.valueOf(number), op);

       }catch (NumberFormatException ex){

           numberField.setText(" " );

       }

   }

   lastOperation = op;

   operationField.setText(lastOperation);

}

 

private void performOperation(Double number, String operation){

 

            // если операнд ранее не был установлен (при вводе самой первой операции)

   if(operand ==null){

       operand = number;

   }

   else{

       if(lastOperation.equals(" =" )){

           lastOperation = operation;

       }

       switch(lastOperation){

           case " =":

               operand =number;

               break;

           case " /":

               if(number==0){

                   operand =0.0;

               }

               else{

                   operand /=number;

               }

               break;

           case " *":

               operand *=number;

               break;

           case " +":

               operand +=number;

               break;

           case " -":

               operand -=number;

               break;

       }

   }

   resultField.setText(operand.toString().replace('.', ', '));

   numberField.setText(" " );

}

}

Разберем этот код. Вначале в методе onCreate() получаем все поля из activity_main.xml, текст которых будет изменяться:

resultField =(TextView) findViewById(R.id.resultField);

numberField = (EditText) findViewById(R.id.numberField);

operationField = (TextView) findViewById(R.id.operationField);

Результат операции будет попадать в переменную operand, которая представляет тип Double, а знак операции - в переменную lastOperation:

Double operand = null;

String lastOperation = " =";

Так как при переходе от портретной ориентации к альбомной или наоборот мы можем потерять все введенные данные, то чтобы их не потерять, мы их сохраняем в методе onSaveInstanceState() и обратно получаем в методе onRestoreInstanceState().

При нажатии на числовую кнопку будет вызываться метод onNumberClick, в котором добавляем введенную цифру или знак запятой к тексту в поле numberField:

Button button = (Button)view;

numberField.append(button.getText());

 

if(lastOperation.equals(" =" ) & & operand! =null){

operand = null;

}

При этом если последняя операция представляла собой получение результата (знак " равно" ), то мы сбрасываем переменную operand.

В методе onOperationClick происходит обработка нажатия на кнопку со знаком операции:

Button button = (Button)view;

String op = button.getText().toString();

String number = numberField.getText().toString();

if(number.length()> 0){

   number = number.replace(', ', '.');

   try{

          performOperation(Double.valueOf(number), op);

   }catch (NumberFormatException ex){

          numberField.setText(" " );

   }

}

lastOperation = op;

operationField.setText(lastOperation);

Здесь получаем ранее введенное число и введенную операцию и передаем их в метод performOperation(). Так как в метод передается не просто строка, а число Double, то нам надо преобразовать строку в чсло. И поскольку теоретически могут быть введены нечисловые символы, то для отлова исключения, которое может возникнуть при преобразовании используется конструкция try...catch.

Кроме того, так как разделителем целой и дробной части в Double в java является точка, то нам надо заменить запятую на точку, так как предполагается, что мы используем в качестве разделителя запятую.

А методе performOperation() выполняем собственно операцию. При вводе первой операции, когда операнд еще не установлен, мы просто устанавливаем операнд:

if(operand ==null){

operand = number;

}

При вводе второй и последующих операций применяем предыдущую операцию, знак которой хранится в переменной lastOperation, к операнду operand и второму числу, которое было введено в числовое поле. Полученный результат операции сохраняем в переменной operand.



Всплывающие окна. Toast

Для создания простых уведомлений в Android используется класс Toast. Фактически Toast представляет всплывающее окно с некоторым текстом, которое отображается в течение некоторого времени.

Объект Toast нельзя создать в коде разметки xml, например, в файл activity_main.xml. Toast можно использовать только в коде java.

Так, определим в файле разметки activity_main.xml кнопку:

< RelativeLayout

xmlns: android=" http: //schemas.android.com/apk/res/android"

android: id=" @+id/activity_main"

android: layout_width=" match_parent"

android: layout_height=" match_parent"

android: padding=" 16dp" >

 

< Button

   android: layout_width=" wrap_content"

   android: layout_height=" wrap_content"

   android: text=" Click"

   android: onClick=" onClick" />

 

< /RelativeLayout>

У кнопки установлен обработчик нажатия - метод onClick. Определим его в коде MainActivity:

package com.example.eugene.layoutapp;

 

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.Toast;

 

public class MainActivity extends AppCompatActivity {

 

@Override

protected void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState);

 

   setContentView(R.layout.activity_main);

}

 

public void onClick(View view){

   Toast toast = Toast.makeText(this, " Hello Android 7", Toast.LENGTH_LONG);

   toast.show();

}

}

В обработчике отображается всплывающее окно. Для его создания применяется метод Toast.makeText(), в который передается три параметра: текущий контекст (текущий объект activity), отображаемый текст и время отобажения окна.

В качестве времени показа окна мы можем использовать целочисленное значение - колическо миллисекунд или встроенные константы Toast.LENGTH_LONG (3500 миллисекунд) и Toast.LENGTH_SHORT (2000 миллисекунд).

Для самого отображения окна вызывается метод show():

По умолчанию окно отображается внизу интерфейса с центрированием по центру. Но мы можем кастомизировать позиционирование окна с помощью методов setGravity() и setMargin(). Так, изменим метод onClick:

public void onClick(View view){

   

   Toast toast = Toast.makeText(this, " Hello Android 7", Toast.LENGTH_LONG);

toast.setGravity(Gravity.TOP, 0, 160);

toast.show();

}

Первый параметр метода setGravity указывает, в какой части контейнера надо позиционировать Toast, второй и третий параметр устанавливают отступы от этой позиции по горизонтали и вертикали сооветственно:

Метод setMargin() принимает два параметра: отступ от левой границы контейнера в процентах от шиирины контейнера и отступ от верхней границы в процентах от длины контейнера.



Snackbar

Элемент Snackbar в некотором роде похож на Toast: он также позволяет выводить всплывающие сообщения, но теперь сообщения растягиваются по ширине экрана.

При создании проекта по типу Empty Activity по умолчанию функциональность Snackbar может быть недоступна, нам ее надо будет добавить. Для этого перейдем к файлу build.gradle, который находится внутри модуля app:

Он выглядит примерно так:

apply plugin: 'com.android.application'

 

android {

compileSdkVersion 25

buildToolsVersion " 23.0.1"

defaultConfig {

   applicationId " com.example.eugene.layoutapp"

   minSdkVersion 16

   targetSdkVersion 25

   versionCode 1

   versionName " 1.0"

   testInstrumentationRunner " android.support.test.runner.AndroidJUnitRunner"

}

buildTypes {

   release {

       minifyEnabled false

       proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

   }

}

}

 

dependencies {

compile fileTree(dir: 'libs', include: ['*.jar'])

androidTestCompile('com.android.support.test.espresso: espresso-core: 2.2.2', {

   exclude group: 'com.android.support', module: 'support-annotations'

})

compile 'com.android.support: appcompat-v7: 25.1.0'

testCompile 'junit: junit: 4.12'

}

В конец секции dependencies добавим нужный нам пакет:

dependencies {

compile fileTree(dir: 'libs', include: ['*.jar'])

androidTestCompile('com.android.support.test.espresso: espresso-core: 2.2.2', {

   exclude group: 'com.android.support', module: 'support-annotations'

})

compile 'com.android.support: appcompat-v7: 25.1.0'

testCompile 'junit: junit: 4.12'

   compile 'com.android.support: design: 25.1.0'

}

Следует отметить, что для компиляции в данном случае применяется API 25 (compileSdkVersion 25), поэтому и у пакета версия начинается с этого числа: 25.1.0.

После изменения файла вверху в Android Studio появится сообщение о необходимости выполнить синхронизацию, и для этого нажмем на ссылку Sync Now:

После завершения синхронизации изменим файл activity_main.xml:

< RelativeLayout xmlns: android=" http: //schemas.android.com/apk/res/android"

android: layout_width=" match_parent"

android: layout_height=" match_parent" >

 

< Button

   android: layout_width=" wrap_content"

   android: layout_height=" wrap_content"

   android: text=" CLICK"

   android: onClick=" onClick" />

< /RelativeLayout>

Здесь определена кнопка, по нажатию на которую будет оображаться сообщение.

И также изменим класс MainActivity:

package com.example.eugene.layoutapp;

 

import android.os.Bundle;

import android.support.design.widget.Snackbar;

import android.support.v7.app.AppCompatActivity;

import android.view.View;

 

public class MainActivity extends AppCompatActivity {

 

protected void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState);

   setContentView(R.layout.activity_main);

}

  public void onClick(View view){

   Snackbar.make(view, " Hello Android 7", Snackbar.LENGTH_LONG)

          .show();

}

}

Snackbar создается с помощью метода make(), в который передаются три параметра: объект View, к которому прикрепляется высплывающее ообщение, само сообщение в виде строки и параметр, который указывает, сколько будет отображаться сообщение. Последний параметр может принимать числовое значение - количество миллисекунд, либо одну из трех констант: Snackbar.LENGTH_INDEFINITE (отображение в течение неопределенного периода времени), Snackbar.LENGTH_LONG (долгое отображение) или Snackbar.LENGTH_SHORT (недолгое отображение).

После создания Snackbar отображается с помощью метода show:

При этом в отличие от Toast мы не можем повлиять на позицию сообщения, оно отображается внизу экрана и занимает всю нижнюю часть.

 



Checkbox

Элементы Checkbox представляют собой флажки, которые могут находиться в отмеченном и неотмеченном состоянии. Флажки позволяют производить множественный выбор из нескольких значений. Итак, определим в файле разметки activity_main.xml несколько флажков:

< LinearLayout xmlns: android=" http: //schemas.android.com/apk/res/android" android: id=" @+id/activity_main" android: layout_width=" match_parent" android: layout_height=" match_parent" android: orientation=" vertical" android: padding=" 16dp" > < TextView android: id=" @+id/selection"      android: layout_width=" match_parent"    android: layout_height=" wrap_content"    android: textSize=" 26sp" /> < CheckBox android: id=" @+id/java"    android: layout_width=" wrap_content"    android: layout_height=" wrap_content"    android: text=" Java"    android: textSize=" 26sp"    android: onClick=" onCheckboxClicked" /> < CheckBox android: id=" @+id/javascript"    android: layout_width=" wrap_content"    android: layout_height=" wrap_content"    android: text=" JavaScript"    android: textSize=" 26sp"    android: onClick=" onCheckboxClicked" /> < /LinearLayout>

Атрибут android: onClick, как и в случае с простыми кнопками, позволяет задать обработчик нажатия на флажок. Определим обработчик нажатия в коде MainActivity:

package com.example.eugene.layoutapp; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.CheckBox; import android.widget.TextView; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) {   super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main); } public void onCheckboxClicked(View view) {   // Получаем флажок   CheckBox language = (CheckBox) view;    // Получаем, отмечен ли данный флажок   boolean checked = language.isChecked();    TextView selection = (TextView) findViewById(R.id.selection);    // Смотрим, какой именно из флажков отмечен   switch(view.getId()) {       case R.id.java:            if (checked){               selection.setText(" Java" );                               }           break;        case R.id.javascript:            if (checked)               selection.setText(" JavaScript" );            break;    } }}

В качестве параметра в обработчик нажатия onCheckboxClicked передается нажатый флажок. С помощью метода isChecked() можно узнать, выделен ли флажок - в этом случае метод возвращает true.

С помощью конструкции switch...case можно получить id нажатого флажка и выполнить соответствующие действия.

Правда, если нам просто надо взять текст из выбранного флажка, то необязательно в данном случае использовать конструкцию switch, так как мы можем сократить весь код следующим образом:

public void onCheckboxClicked(View view) { // Получаем флажок CheckBox language = (CheckBox) view; // Получаем, отмечен ли данный флажок TextView selection = (TextView) findViewById(R.id.selection); if(language.isChecked())   selection.setText(language.getText()); }

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

package com.example.eugene.layoutapp; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.CheckBox; import android.widget.TextView; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) {   super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main); } public void onCheckboxClicked(View view) {    // Получаем флажки   CheckBox java = (CheckBox) findViewById(R.id.java);    CheckBox javascript = (CheckBox) findViewById(R.id.javascript);    String selectedItems = " ";    if(java.isChecked())       selectedItems +=java.getText() + ", ";    if(javascript.isChecked())       selectedItems +=javascript.getText();    TextView selection = (TextView) findViewById(R.id.selection);    selection.setText(selectedItems); } }

OnCheckedChangeListener

С помощью слушателя OnCheckedChangeListener можно отслеживать изменения флажка. Этот слушатель срабатывает, когда мы устанавливаем или убираем отметку на флажке. Например, определим следующий checkbox:

< LinearLayout xmlns: android=" http: //schemas.android.com/apk/res/android" android: id=" @+id/activity_main" android: layout_width=" match_parent" android: layout_height=" match_parent" android: orientation=" vertical" android: padding=" 16dp" > < CheckBox android: id=" @+id/enabled"    android: layout_width=" wrap_content"    android: layout_height=" wrap_content"    android: checked=" true"    android: text=" Включить"    android: textSize=" 26sp" /> < /LinearLayout>

В коде MainActivity подключим обработчик изменения состояния:

package com.example.eugene.layoutapp; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.Toast; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) {   super.onCreate(savedInstanceState);      setContentView(R.layout.activity_main);    CheckBox enableBox = (CheckBox) findViewById(R.id.enabled);    enableBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {       public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {            if (isChecked) {               Toast.makeText(getApplicationContext(), " Включено", Toast.LENGTH_SHORT).show();            } else {               Toast.makeText(getApplicationContext(), " Выключено", Toast.LENGTH_SHORT).show();            }       }   }); }}

Слушатель OnCheckedChangeListener определен в базовом классе CompoundButton и определяет один метод - onCheckedChanged. Первый параметр этого метода buttonView - сам измененный флажок CheckBox. А второй параметр isChecked указывает, отмечен ли флажок.

При изменении состояния флажка будет выводиться во всплывающем окне соответствующее уведомление:



ToggleButton

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

< LinearLayout xmlns: android=" http: //schemas.android.com/apk/res/android"

xmlns: tools=" http: //schemas.android.com/tools"

android: layout_width=" match_parent"

android: layout_height=" match_parent"

android: orientation=" vertical" >

 

< ToggleButton

   android: id=" @+id/toggle"

   android: layout_width=" wrap_content"

      android: layout_height=" wrap_content"

   android: textOn=" Включено"

   android: textOff=" Выключено"

   android: onClick=" onToggleClicked" />

 

< /LinearLayout>

Атрибуты android: textOn и android: textOff задают текст кнопки в отмеченном и неотмеченном состоянии соответственно. И также, как и для других кнопок, мы можем обработать нажатие на элемент с помощью события onClick. В этом случае определим в классе Activity обработчик события:

package com.example.eugene.layoutapp;

 

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.Toast;

import android.widget.ToggleButton;

 

public class MainActivity extends AppCompatActivity {

 

@Override

protected void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState);

 

  setContentView(R.layout.activity_main);

}

 

public void onToggleClicked(View view) {

 

   // включена ли кнопка

   boolean on = ((ToggleButton) view).isChecked();

 

   if (on) {

       // действия если включена

       Toast.makeText(this, " Свет включен", Toast.LENGTH_LONG).show();

   } else {

       // действия, если выключена

       Toast.makeText(this, " Свет выключен! ", Toast.LENGTH_LONG).show();

   }

}

}

Создание элемента ToggleButton в коде java:

package com.example.eugene.layoutapp;

 

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.LinearLayout;

import android.widget.Toast;

import android.widget.ToggleButton;

 

public class MainActivity extends AppCompatActivity {

 

@Override

protected void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState);

 

   LinearLayout linearLayout = new LinearLayout(this);

   ToggleButton toggleButton = new ToggleButton(this);

   toggleButton.setTextOff(" Выключено" );

   toggleButton.setTextOn(" Включено" );

   toggleButton.setText(" Выключено" );

   toggleButton.setOnClickListener(new View.OnClickListener() {

       @Override

       public void onClick(View view) {

           boolean on = ((ToggleButton) view).isChecked();

 

           if (on) {

               Toast.makeText(getApplicationContext(), " Свет включен", Toast.LENGTH_LONG).show();

           } else {

               Toast.makeText(getApplicationContext(), " Свет выключен! ", Toast.LENGTH_LONG).show();

           }

       }

   });

   linearLayout.addView(toggleButton, new LinearLayout.LayoutParams

           (LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));

   setContentView(linearLayout);

}

}



RadioButton

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

Чтобы создать список переключателей для выбора, вначале надо создать объект RadioGroup, который будет включать в себя все переключатели:

< LinearLayout xmlns: android=" http: //schemas.android.com/apk/res/android" xmlns: tools=" http: //schemas.android.com/tools" android: layout_width=" match_parent" android: layout_height=" match_parent" android: orientation=" vertical" > < TextView android: id=" @+id/selection"    android: layout_width=" match_parent"    android: layout_height=" wrap_content"    android: textSize=" 26sp"    /> < RadioGroup xmlns: android=" http: //schemas.android.com/apk/res/android"    android: id=" @+id/radios"    android: layout_width=" match_parent"    android: layout_height=" wrap_content"    android: orientation=" vertical" >    < RadioButton android: id=" @+id/java"        android: layout_width=" wrap_content"        android: layout_height=" wrap_content"        android: text=" Java"        android: onClick=" onRadioButtonClicked" />    < RadioButton android: id=" @+id/javascript"        android: layout_width=" wrap_content"        android: layout_height=" wrap_content"        android: text=" JavaScript"        android: onClick=" onRadioButtonClicked" /> < /RadioGroup> < /LinearLayout>

Поскольку класс RadioGroup является производным от LinearLayout, то мы также можем задать вертикальную или горизонтальную ориентацию списка, при том включив в него не только собственно переключатели, но и другие объекты, например, кнопку или TextView.

В классе MainActivity определим обработку выбора переключателей:

package com.example.eugene.layoutapp; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.RadioButton; import android.widget.TextView; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) {   super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main); }   public void onRadioButtonClicked(View view) {   // если переключатель отмечен   boolean checked = ((RadioButton) view).isChecked();    TextView selection = (TextView) findViewById(R.id.selection);    // Получаем нажатый переключатель   switch(view.getId()) {       case R.id.java:            if (checked){               selection.setText(" Выбран Java" );            }           break;        case R.id.javascript:            if (checked){               selection.setText(" Выбран JavaScript" );            }           break;    } }}

OnCheckedChangeListener

Кроме обработки нажатия на каждый отдельный переколючатель мы можем в целом повесить на весь RadioGroup с его переключателями слушатель OnCheckedChangeListener и обрабатывать в нем нажатия. Для этого уберем из разметки у переключателей атрибуты android: onClick, а у элемента RadioGroup определим id:

< LinearLayout xmlns: android=" http: //schemas.android.com/apk/res/android" xmlns: tools=" http: //schemas.android.com/tools" android: layout_width=" match_parent" android: layout_height=" match_parent" android: orientation=" vertical" > < TextView android: id=" @+id/selection"    android: layout_width=" match_parent"    android: layout_height=" wrap_content"    android: textSize=" 26sp"    /> < RadioGroup xmlns: android=" http: //schemas.android.com/apk/res/android"    android: id=" @+id/radios"    android: layout_width=" match_parent"    android: layout_height=" wrap_content"    android: orientation=" vertical" >    < RadioButton android: id=" @+id/java"        android: layout_width=" wrap_content"        android: layout_height=" wrap_content"        android: text=" Java" />    < RadioButton android: id=" @+id/javascript"        android: layout_width=" wrap_content"        android: layout_height=" wrap_content"        android: text=" JavaScript" /> < /RadioGroup> < /LinearLayout>

Далее в коде MainActivity повесим на объект RadioGroup слушатель OnCheckedChangeListener:

package com.example.eugene.layoutapp; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.TextView; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) {   super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    // получаем объект RadioGroup   RadioGroup radGrp = (RadioGroup)findViewById(R.id.radios);    // обработка переключения состояния переключателя   radGrp.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {       @Override       public void onCheckedChanged(RadioGroup arg0, int id) {           TextView selection = (TextView) findViewById(R.id.selection);            switch(id) {               case R.id.java:                    selection.setText(" Выбран Java" );                    break;                case R.id.javascript:                    selection.setText(" Выбран JavaScript" );                    break;                default:                    break;            }       }}); }}

Слушатель RadioGroup.OnCheckedChangeListener определяет метод onCheckedChanged(), в который передается объект RadioGroup и id выделенного переключателя. Далее также мы можем проверить id и выполнить определенную обработку.



DatePicker и TimePicker

DatePicker и TimePicker представляет собой элементы для выбора даты и времени соответственно. Итак, создадим разметку для этих элементов:

<? xml version=" 1.0" encoding=" utf-8"? > < LinearLayout xmlns: android=" http: //schemas.android.com/apk/res/android"         android: orientation=" vertical"         android: layout_        android: layout_height=" match_parent" >    < TextView android: id=" @+id/dateDefault"     android: layout_   android: layout_height=" wrap_content" />      < DatePicker android: id=" @+id/datePicker"     android: layout_   android: layout_height=" wrap_content" />    < TextView android: id=" @+id/timeDefault"     android: layout_   android: layout_height=" wrap_content" />      < TimePicker android: id=" @+id/timePicker"     android: layout_   android: layout_height=" wrap_content" />  < /LinearLayout>

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

protected void onCreate(Bundle savedInstanceState) {   super.onCreate(savedInstanceState);   setContentView(R.layout.activity_main);           TextView dateDefault = (TextView)findViewById(R.id.dateDefault);        TextView timeDefault = (TextView)findViewById(R.id.timeDefault);                DatePicker dp = (DatePicker)this.findViewById(R.id.datePicker);        // Месяц начиная с нуля. Для отображения добавляем 1.  dateDefault.setText(" Дата по умолчанию " + dp.getDayOfMonth() + " /" +                                     (dp.getMonth() + 1) + " /" + dp.getYear());               dp.init(2015, 02, 01, null);        TimePicker tp = (TimePicker)this.findViewById(R.id.timePicker);        java.util.Formatter timeF = new java.util.Formatter();        timeF.format(" Время по умолчанию %d: %02d", tp.getCurrentHour(),                        tp.getCurrentMinute());        timeDefault.setText(timeF.toString());        tp.setIs24HourView(true);        tp.setCurrentHour(new Integer(10));        tp.setCurrentMinute(new Integer(10));     }

Используя метод dp.init(2015, 02, 01, null); устанавливаем дату по умолчанию - 1 марта, так как отсчет месяцев идет с нуля. А перед отображением времени, прибегаем к форматированию.


Поделиться:



Последнее изменение этой страницы: 2019-05-04; Просмотров: 397; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (2.376 с.)
Главная | Случайная страница | Обратная связь