четверг, 26 февраля 2015 г.

Полосы прокрутки

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

Полосы прокрутки в Android представляют элементы ScrollView и HorizontalScrollView, которые являются контейнерными элементами и наследуются от ViewGroup.


Элементы ScrollView и HorizontalScrollView — это контейнеры типа FrameLayout. Это означает, что в них можно расположить только одно дочернее представление. Этот дочерний элемент может, в свою очередь, быть контейнером со сложной иерархией объектов. В качестве дочернего элемента для полос прокрутки обычно используют LinearLayout с вертикальной или горизонтальной ориентацией элементов.

Элемент ScrollView, несмотря на свое название, поддерживает только вертикальную прокрутку, поэтому для создания вертикальной и горизонтальной прокрутки необходимо использовать ScrollView в сочетании с HorizontalScrollView. Обычно ScrollView используют в качестве корневого элемента, а HorizontalScrollView — дочернего.

Рассмотрим создание полос прокрутки на практике. Cоздайте новый проект ScrollsApp. Откройте файл компоновки main.xml и создайте структуру компоновки, разместив в ней ScrollView, HorizontalScrollView и TextView.
Файл компоновки main.xml
<ScrollView xmlns:android=
      "http://schemas.android.com/apk/res/android"
    android:id="@+id/scroll"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <HorizontalScrollView
        android:id="@+id/scroll_hor"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">

        <TextView
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#000000"
            android:background="#FFFFFF"
            android:textSize="24px"
            android:shadowDx="0"
            android:shadowDy="0"
            android:shadowRadius="0"
            android:shadowColor="#FFFFFF"
            android:isScrollContainer="true"/>

    </HorizontalScrollView>
</ScrollView>
В классе MainActivity в теле метода onCreate() создайте ссылку на элемент TextView, объявленный в XML-компоновке, и запишите в него методом setText() достаточно большой текст, который гарантированно не поместится в видимые размеры экрана устройства.
Файл класса окна приложения MainActivity.java
package com.samples.ui.scrolls;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TextView text = (TextView)findViewById(R.id.text);

        // Загружаем текст
        text.setText("..."); // Введите любой достаточно большой текст
    }
}
Выполните компиляцию проекта и запустите его на мобильном устройстве. Полосы прокрутки представляют собой тонкие линии справа или внизу, которые появляются при касании экрана пальцем или движении пальца по экрану.


EditText, InputMode

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

Настройка режимов отображения устанавливается в файле манифеста приложения для каждого Activity, входящего в состав приложения. В элементе <activity> для этого существует необязательный атрибут (по умолчанию он отсутствует) android:windowSoftInputMode.

Этот атрибут определяет два типа вариантов поведения экранной клавиатуры и текстовых полей, находящихся в данном Activity — состояние отображения экранной клавиатуры и поведение текстовых полей при получении или потере фокуса и вводе текста.

Варианты поведения экранной клавиатуры могут быть следующими:
  • stateUnspecified — система сама выбирает подходящее поведение экранной клавиатуры. Это настройка по умолчанию;
  • stateUnchanged — экранная клавиатура при получении Activity (на котором текстовое поле) фокуса ввода сохраняет свое последнее состояние, видимое или скрытое;
  • stateHidden — экранная клавиатура скрыта, когда пользователь открывает Activity. Клавиатура появится при наборе текста. Если пользователь перейдет к следующему Activity, клавиатура скроется. Но при возвращении назад клавиатура останется на экране, если она была видима при закрытии Activity;
  • stateAlwaysHidden — экранная клавиатура всегда скрывается, если Activity получает фокус;
  • stateVisible — экранная клавиатура видима в обычном режиме (поведение такое же, как в приложении из предыдущего раздела);
  • stateAlwaysVisible — экранная клавиатура отображается сразу, когда пользователь открывает Activity.
Для определения поведения текстовых полей имеется три значения:
  • adjustResize — размеры элементов, находящихся на Activity, могут изменяться, освобождая место для экранной клавиатуры;
  • adjustPan — окно Activity и его элементы не изменяются при отображении экранной клавиатуры, только автоматически подстраиваются, чтобы текстовое поле, находящееся в фокусе ввода, не было закрыто клавиатурой. Такое поведение используется реже, т. к. остальные элементы, находящиеся на этом Activity, например кнопки, становятся недоступными, и надо закрывать клавиатуру для доступа к ним;
  • adjustUnspecified — система Android автоматически выберет один из перечисленных ранее режимов в зависимости от компоновки окна Activity и количества дочерних элементов управления на нем. Это настройка по умолчанию для Activity.
Поведение экранной клавиатуры и текстовых полей в атрибуте android:windowSoftInputMode задается их комбинацией с использованием знака |, например, так:

<activity
    android:windowSoftInputMode="stateVisible|adjustResize"
    . . .
</activity>
Чтобы разобраться, как эти настройки поведения экранной клавиатуры и текстовых полей выглядят на экране, создадим новый проект EditTextInputModes. В файл манифеста приложения добавим атрибут android:windowSoftInputMode и выставим ему значение stateVisible|adjustPan.
Файл манифеста приложения AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android=
      "http://schemas.android.com/apk/res/android"
    package="com.samples.ui.edittextinputmode"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk android:minSdkVersion="10" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:label="@string/app_name"
            android:name=".EditInputModeActivity"
            android:windowSoftInputMode="stateVisible|adjustPan">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>
В файле компоновки main.xml окна приложения используем три текстовых поля такого же типа, как в предыдущей программе, но внесем некоторые изменения — с помощью атрибутов android:layout_height и android:layout_weight равномерно распределим эти поля на весь экран.
Файл компоновки main.xml для проекта EditTextInputModes
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android=
      "http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <EditText
        android:id="@+id/editText1"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:inputType="textEmailAddress"
        android:layout_weight="1"
        android:hint="Enter e-mail"/>
    <EditText
        android:id="@+id/editText2"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:inputType="number"
        android:hint="Enter number"
        android:layout_weight="1" />
    <EditText
        android:id="@+id/editText3"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:inputType="textPassword"
        android:hint="Enter password"
        android:layout_weight="1" />
</LinearLayout>
Если запустить приложение и начать вводить информацию в текстовые поля, будет отображена экранная клавиатура и одновременно пропорционально уменьшатся размеры по вертикали всех текстовых полей.


Теперь изменим поведение приложения, поменяв значение в атрибуте android:windowSoftInputMode в манифесте приложения:

android:windowSoftInputMode="stateVisible|adjustPan"
Если перекомпилировать и запустить приложение, то при вводе текста в режиме adjustPan экранная клавиатура будет затенять часть окна Activity вместе с элементами.


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



EditText, InputType

Возможность автоматического появления экранной клавиатуры заложена для всех элементов, в которых предусмотрен ввод текста. В группе Text Fields панели Palette редактора компоновки находится множество вариантов текстовых полей с различным режимом ввода текста.


Давайте поэкспериментируем с несколькими типами текстовых полей. Создайте новый проект c с именем EditTextInputTypes. В файл компоновки из группы Text Fields добавьте три текстовых поля разного типа: E-mail, Number и Password.
Файл компоновки main.xml для проекта EditTextInputTypes
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android=
      "http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <EditText
        android:id="@+id/editText1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textEmailAddress"/>
    <EditText
        android:id="@+id/editText3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="number" />
    <EditText
        android:id="@+id/editText4"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textPassword" />
</LinearLayout>
Как вы видите, на самом деле все эти текстовые поля представлены одним элементом EditText, а тип ввода текста определяется одним атрибутом android:inputType. Запустите приложение на выполнение. Если теперь попытаться ввести что-нибудь в текстовые поля, в зависимости от типа поля система будет отображать соответствующую экранную клавиатуру. Например, для ввода адреса электронной почты на клавиатуре будет кнопка со значком @ и кнопка перехода Next, а на клавиатуре для ввода пароля вместо Next стоит кнопка Done. Если в текстовое поле разрешено вводить только цифры, будет отображена цифровая клавиатура.


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

EditText

Элемент EditText — это текстовое поле для пользовательского ввода. EditText представляет собой тонкую оболочку над классом TextView, которая позволяет редактировать вводимый пользователем текст.

Основной метод класса EditText — getText(), который возвращает текст, содержащийся в окне элемента EditText. Возвращаемое значение имеет тип Editable. Класс Editable представляет собой интерфейс для текста, информационное наполнение которого может изменяться (в противоположность типу String, который является неизменяемым, при его изменении просто создается новый экземпляр String).

В классе EditText есть метод setHint() для отображения подсказки. С помощью этого метода можно задать текст подсказки, который увидит пользователь в этом элементе, например "Enter some text...".

В классе также определены методы для выделения текста:
  • selectAll() — выделяет весь текст в окне;
  • setSelection(int start, int stop) — выделяет участок текста с позиции start до позиции stop;
  • setSelection(int index) — перемещает курсор на позицию index.
Большинство методов для работы с текстом и его форматированием унаследованы от базового класса TextView. Чаще всего используются методы setTypeface(null, Typeface), setTextSize(int textSize), setTextColor(int Color).

Давайте теперь рассмотрим использование элемента EditText в приложении. Создайте новый проект EditTextApp. В файле компоновки main.xml создадим элемент EditText, в котором добавим выводимую на экран подсказку: android:hint="Enter some text...".
Файл компоновки main.xml для проекта EditTextApp
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android=
      "http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <EditText
        android:id="@+id/text"
        android:layout_height="fill_parent"
        android:layout_width="fill_parent"
        android:hint="Enter some text..."/>
</LinearLayout>
Выполните компиляцию проекта и запустите его на устройстве Android. Внешний вид программы с элементом TextView показан на скриншоте.


При запуске приложения в элементе EditText будет выведена подсказка (мы задавали свойство android:hint в файле компоновки). Когда пользователь начнет вводить текст, на экране автоматически появится экранная клавиатура.

среда, 4 февраля 2015 г.

Элемент Button, обработка событий

Элемент Button

Класс Button  — самый простой из всех элементов управления и при этом
самый используемый. Чаще всего кнопка требует написания кода обработки события нажатия onClick().

Напишем программу, которая реализует обработчик события нажатия на кнопку. В программе будут две кнопки и текстовое поле TextView. Когда пользователь нажимает кнопку, в элемент TextView будет выводиться сообщение о событии.
Создайте в новый проект, откройте файл компоновки и создайте компоновку LinearLayout и в ней две кнопки с идентификаторами button1 и button2 и надписями Button 1 и Button 2.

Файл компоновки main.xml
<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 
 
    <Button  
        android:id="@+id/button1"  
        android:layout_height="wrap_content"  
        android:layout_width="fill_parent" 
        android:text="Button 1"/> 
    <Button  
        android:id="@+id/button2"  
        android:layout_height="wrap_content"  
        android:layout_width="fill_parent" 
        android:text="Button 2" /> 
    <TextView  
        android:id="@+id/text" 
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="Event:"  
        android:textStyle="bold"/> 
         
</LinearLayout> 

Теперь в классе ButtonActivity подключим обработчики событий для кнопок.

Обработка событий

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

Класс View содержит коллекцию вложенных интерфейсов, называемых On...Listener(), в каждом из которых объявлен единственный абстрактный метод. Этот метод необходимо переопределить в вашем классе. Его будет вызывать система Android, когда c экземпляром View, к которому был подсоединен слушатель события, будет взаимодействовать пользователь.

Всего класс View содержит шесть вложенных интерфейсов:
  • OnClickListener;
  • OnLongClickListener;
  • OnFocusChangeListener;
  • OnKeyListener;
  • OnTouchListener;
  • OnCreateContextMenuListener.
Например, если требуется, чтобы командная кнопка получила уведомление о нажатии ее пользователем, необходимо в классе окна реализовать интерфейс OnClickListener и определить его метод обратного вызова onClick(), куда будет помещен код обработки нажатия кнопки, и зарегистрировать слушателя события с помощью метода setOnClickListener():

button1.setOnClickListener(new View.OnClickListener() { 
public void onClick(View v) { 
        mText.setText("Click on Button"); 
    } 
});

Реализуем обработчики событий в нашем классе MainActivity:

Файл класса окна приложения MainActivity.java
package com.example.button1; 
 
import android.app.Activity; 
import android.os.Bundle; 
import android.widget.Button; 
import android.widget.TextView; 
import android.view.View; 
 
public class MainActivity extends Activity { 
        
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
         
        final TextView mText = (TextView)findViewById(R.id.text); 
         
        final Button button1 = (Button)findViewById(R.id.button1); 
        button1.setOnClickListener(new View.OnClickListener() { 
            public void onClick(View v) { 
                mText.setText("Click on First Button"); 
            } 
        }); 
         
        final Button button2 = (Button)findViewById(R.id.button2); 
        button2.setOnClickListener(new View.OnClickListener() { 
            public void onClick(View v) { 
                mText.setText("Click on Second Button"); 
            } 
        }); 
    } 
}

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


Существуют и другие варианты обработки событий. В предыдущем примере обработчики событий были реализованы внутри тела метода onCreate(). Наличие множества вложенных блоков кода создает трудности его восприятия, особенно другими программистами, поэтому желательно выносить обработчики событий за пределы метода onCreate(). В методе setOnClickListener() в качестве параметра передается имя метода обработчика, который мы должны будем реализовать:

button.setOnClickListener(button_click);

Далее мы описываем реализацию этого метода:

public OnClickListener button_click = new OnClickListener() {
    @Override
    public void onClick(View v) {
        // Действия по обработке события
    }
};

Внесите в класс MainActivity изменения, как показано в листинге 8.3, и скомпилируйте проект. Результат не изменился, но код класса стал легче для восприятия.

Подключение обработчиков событий. 2-й вариант
package com.example.button2; 
 
import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.TextView; 
 
public class MainActivity extends Activity { 
    private TextView text; 
     
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
         
        text = (TextView)findViewById(R.id.text); 
         
        final Button button1 = (Button)findViewById(R.id.button1); 
        final Button button2 = (Button)findViewById(R.id.button2); 
         
        button1.setOnClickListener(button1_click); 
        button2.setOnClickListener(button2_click); 
         
    } 
     
    public OnClickListener button1_click = new View.OnClickListener() { 
        public void onClick(View v) { 
            text.setText("Click on First Button"); 
        } 
    }; 
     
     
    public OnClickListener button2_click = new View.OnClickListener() { 
        public void onClick(View v) { 
            text.setText("Click on Second Button"); 
        } 
    }; 
}

Наконец, есть еще способ, более эффективный, чем предыдущие, — реализовать обработку однотипных событий всех элементов в одном методе. Для этого в нашем классе необходимо реализовать интерфейс View.OnClickListener:

public class MainActivity extends Activity
    implements View.OnClickListener

Этот интерфейс содержит единственный метод:

abstract void onClick(View v)

который необходимо определить в нашем классе ButtonActivity. Если определен идентификатор элемента (например, в файле компоновки Activity), то можно написать обработку событий элементов в операторе switch, получив ID элемента методом getId():

@Override
public void onClick(View v) {
    switch (v.getId()) {
        // Определяем ID элемента и обрабатываем событие
    }
}

Если в методе onClick() обрабатывается только одно событие, структура switch не нужна.
Теперь используем данный способ обработки событий в нашем приложении, изменив код класса ButtonActivity.

Подключение обработчиков событий. 3-й вариант
package com.example.button3; 
 
import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.Button; 
import android.widget.TextView; 
 
public class MainActivity extends Activity  
        implements View.OnClickListener { 
    private TextView text; 
     
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
         
        text = (TextView)findViewById(R.id.text); 
         
        final Button button1 = (Button)findViewById(R.id.button1); 
        final Button button2 = (Button)findViewById(R.id.button2); 
         
        button1.setOnClickListener(this); 
        button2.setOnClickListener(this); 
         
    } 
     
    @Override 
    public void onClick(View v) { 
        switch (v.getId()) { 
        case R.id.button1: 
            text.setText("Click on First Button"); 
            break; 
        case R.id.button2: 
            text.setText("Click on Second Button"); 
            break; 
        } 
    } 
}

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

Код можно еще упростить, если вынести объявление обработчика события кнопок в файл компоновки. Для этого надо добавить для каждой кнопки android:onClick="onClick".


Подключение обработчиков событий. 4-й вариант
<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 
 
    <Button  
        android:id="@+id/button1"  
        android:layout_height="wrap_content"  
        android:text="Button 1"  
        android:onClick="onClick" 
        android:layout_width="fill_parent"/> 
    <Button  
        android:id="@+id/button2"  
        android:layout_height="wrap_content"  
        android:text="Button 2"  
        android:onClick="onClick" 
        android:layout_width="fill_parent"/> 
    <TextView  
        android:id="@+id/text" 
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="Event:"  
        android:textStyle="bold"/> 
         
</LinearLayout> 
В классе MainActivity нам уже не понадобится для каждой кнопки подключать обработчик setOnClickListener.

Класс MainActivity. 4-й вариант
package com.example.button4; 
 
import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.TextView; 
 
public class MainActivity extends Activity  
        implements View.OnClickListener { 
    private TextView text; 
     
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
         
        text = (TextView)findViewById(R.id.text);        
    } 
     
    @Override 
    public void onClick(View v) { 
        switch (v.getId()) { 
        case R.id.button1: 
            text.setText("Click on First Button"); 
            break; 
        case R.id.button2: 
            text.setText("Click on Second Button"); 
            break; 
        } 
    } 
}

вторник, 3 февраля 2015 г.

ImageView - отображение графики

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

  • setImageResource(int resId) — загружает изображение по его идентификатору ресурса;
  • setImageURI(Uri uri) — загружает изображение по его URI;
  • setImageBitmap(Bitmap bitmap)— загружает растровое изображение.

Для загрузки изображения в XML-файле компоновки используется атрибут android:src.
Кроме того, в классе ImageView определены методы для установки размеров изображения — setMaxHeight(), setMaxWidth(), getMinimumHeight(), getMinimumWidth(), а также его масштабирования — getScaleType(), setScaleType().
Создайте новый проект и в каталог res/drawable/ проекта (это общий каталог для хранения графики, он у вас пустой) поместите два png-изображения android.png и androidmarker.png.

 


Откройте файл компоновки и создайте структуру компоновки, разместив в ней два элемента ImageView с идентификаторами image1, image2. Для первого элемента задайте атрибут android:src="@drawable/android". Для второго элемента ImageView загрузка ресурса будет происходить в программном коде.
Код файла компоновки:

main.xml
<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:gravity="center" android:orientation="horizontal"> 
     
    <ImageView 
        android:id="@+id/image1"   
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:src="@drawable/android"  
        android:padding="10px"/> 
    <ImageView 
        android:id="@+id/image2"   
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:padding="10px"/> 
</LinearLayout> 
В классе MainActivity загрузите программно изображение для второго элемента
ImageView методом setImageResource()

MainActivity.java
package com.example.textview; 
 
import android.app.Activity; 
import android.os.Bundle; 
import android.widget.TextView; 
 
public class MainActivity extends Activity { 
     
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
         
        final TextView text3 = (TextView)findViewById(R.id.text3); 
        text3.setText("Text from Activity"); 
         
        final TextView text4 = (TextView)findViewById(R.id.text4); 
        text4.setText(R.string.text_hello); 
    } 
}
Выполните компиляцию проекта и запустите его на мобильном устройстве. Результат должен получиться такой:



На следующем уроке мы будем рассматривать кнопки и обработку событий.

TextView - отображение текста

Элемент TextView — самый простой и в то же время один из самых используемых в приложениях элементов. TextView служит для отображения текста без возможности его редактирования.

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

Элемент TextView, так же как и объект View, от которого он наследуется, поддерживает собственное разнообразие XML-атрибутов. Некоторые атрибуты являются определенными только в объекте TextView, но эти атрибуты могут также наследоваться любыми объектами, которые расширяют этот класс.

Свойства для элемента TextView можно задавать как в файле компоновки, так и в программном коде. Например, для отображения текста в TextView в файле компоновки используется атрибут android:text, а в программном коде вызывается метод setText() этого класса.

В целом, XML-словарь элементов пользовательского интерфейса близок к структуре классов и методов этих элементов, где имя элемента соответствует имени класса, а атрибуты элемента — методам этого класса. Фактически, соответствие является часто настолько точным, что легко предположить без обращения к документации Android, какой XML-атрибут передает метод класса или, наоборот, какой метод класса соответствует конкретному XML-элементу. В таблице приведены для примера несколько свойств элемента TextView, чтобы вы могли оценить точность соответствия XML-атрибутов и методов класса TextView.

Соответствие XML-атрибутов и методов в классах представлений

Имя XML-атрибута Соответствующий метод в классе Java
android:text setText()
android:textColor setTextColor()
android:textSize setTextSize()
android:textColorHighlight setHighlightColor()

Однако обратите внимание на последнюю строку в таблице: не всегда XML-словарь идентичен структуре java-классов.

Некоторые атрибуты элемента TextView являются общими по отношению ко всем объектам View, потому что они унаследованы от корневого класса View. Такими атрибутами являются, например, id, layout_width, layout_height, с которыми вы уже познакомились в главе 4.

Если в программном коде мы работаем с данным элементом пользовательского интерфейса, в файле компоновки обязательно определяют идентификатор, например:
android:id="@+id/text1"

где символ @ в начале строки указывает, что синтаксический анализатор XML должен проанализировать и развернуть остальную часть строки идентификатора и определить это выражение как ресурс идентификатора. Символ + означает, что это новое имя ресурса, которое должно быть создано и добавлено к нашим ресурсам в файл R.java, автоматически генерируемый средой Android для проекта.

Требование к уникальности идентификаторов не распространяется на все дерево элементов, но они должны быть уникальны в пределах части дерева (которая нередко может быть и полным деревом, так что лучше создавать совершенно уникальные идентификаторы, если это возможно).

Если планируется создание приложения с многоязыковой поддержкой пользовательского интерфейса, вместо непосредственного задания текста в XML-компо­новке или в коде программы необходимо создать ссылку на текстовый XML-ресурс:

android:text="@string/text_hello"

где text_hello — имя ресурса.

В коде программы ссылка на XML-ресурс задается методом setText(), который принимает ссылку на идентификатор ресурса, определенного в файле R.java (автоматически сгенерированном средой разработки), например:

final TextView text = (TextView)findViewById(R.id.text4); 
        text4.setText(R.string.text_hello); 
У элемента TextView есть многочисленные методы и XML-атрибуты для работы с текстом. Например, основные XML-атрибуты, отображающие свойства элемента TextView:

  • android:textSize;
  • android:textStyle;
  • android:textColor.
Атрибут android:textSize задает размер текста. При этом используют несколько единиц измерения:

  • px (pixels) — пикселы;
  • dp (density-independent pixels) — независимые от плотности пикселы. Это абстрактная единица измерения, основанная на физической плотности экрана;
  • sp (scale-independent pixels) — независимые от масштабирования пикселы;
  • in (inches) — дюймы, базируются на физических размерах экрана;
  • pt (points) — 1/72 дюйма, базируются на физических размерах экрана;
  • mm (millimeters) — миллиметры, также базируются на физических размерах экрана.
Обычно при установке размера текста используются единицы измерения sp, которые наиболее корректно отображают шрифты, например:

android:textSize="48sp";
Атрибут android:textStyle представляет стиль текста (нормальный, полужирный, наклонный). Для задания стиля текста используются только следующие константы:

  • normal;
  • bold;
  • italic.
Вот пример установки стиля через атрибуты в файле компоновки:

android:textStyle="bold";
Атрибут android:textColor задает цвет текста. Для задания цвета используются четыре формата в шестнадцатеричной кодировке:

  • #RGB;
  • #ARGB;
  • #RRGGBB;
  • #AARRGGBB,
где R, G, B — соответствующий цвет, А — альфа-канал (alpha-channel), который определяет прозрачность. Значение A, установленное в 0, означает прозрачность 100%. Значение по умолчанию без указания значения A равно 1, т. е. непрозрачно.

Для всех перечисленных ранее атрибутов в классе TextView есть соответствующие методы для чтения или задания соответствующих свойств.

Сейчас мы создадим простое приложение с элементом TextView, в котором рассмотрим различные способы задания его свойств — через атрибуты в файле компоновки и программно, в коде класса, реализующего окно приложения. Для этого создайте новый проект. Для файла компоновки в уроках будет имя main.xml, так, на мой взгляд, удобнее main.xml, а ему соответствует java-класс MainActivity но, если хотите используйте имя по умолчанию  — activity_main.xml). Откройте файл компоновки добавьте компоновку LinearLayout и в ней четыре элемента TextView с идентификаторами text1, text2, text3, text4.
Для text1 задайте текст непосредственно в XML-коде. Для элемента text2 текст задайте через ссылку на строковый ресурс. Можно также задать различный размер, цвет и стиль форматирования текста для элементов text3 и text4. Полный код файла компоновки:

Файл компоновки main.xml
<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    android:orientation="vertical"> 
     
    <TextView  
        android:id="@+id/text1"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"   
        android:text="Text from res/layout/main.xml"/> 
    <TextView  
        android:id="@+id/text2"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"   
        android:text="@string/text_hello" 
        android:textStyle="bold"/> 
    <TextView  
        android:id="@+id/text3"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:textSize="24sp"  
        android:textStyle="bold"  
        android:textColor="#ABABAB"/> 
    <TextView  
        android:id="@+id/text4"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:textSize="36sp"  
        android:textStyle="italic"/> 
         
</LinearLayout> 
В файле ресурсов strings.xml добавьте после ресурса app_name новый строковый ресурс "Hello, Android!" (листинг 2).

Файл ресурсов strings.xml
<?xml version="1.0" encoding="utf-8"?> 
<resources> 
    <string name="app_name">TextView Sample</string> 
    <string name="text_hello">Text from res/values/string.xml</string> 
    <string name="action_settings">Settings</string> 
</resources>
В классе MainActivity инициализируйте TextView-объекты text3, text4 и методом setText() задайте для них текст. Полный код класса окна приложения:

Файл класса окна приложения MainActivity.java
package com.example.textview; 
 
import android.app.Activity; 
import android.os.Bundle; 
import android.widget.TextView; 
 
public class MainActivity extends Activity { 
     
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
         
        final TextView text3 = (TextView)findViewById(R.id.text3); 
        text3.setText("Text from Activity"); 
         
        final TextView text4 = (TextView)findViewById(R.id.text4); 
        text4.setText(R.string.text_hello); 
    } 
}

Результат должен получиться такой, как на рисунке. Для первого поля текст задается прямо в файле компоновки, для второго — в файле компоновки из строковых ресурсов strings.xml, для третьего — в коде, для четвертого поля — читается в java-коде из файла ресурсов.

Приложение с элементами TextView

В следующем уроке мы рассмотрим работу с элементом ImageView.


суббота, 31 января 2015 г.

Компоновка RelativeLayout

Компоновка RelativeLayout  позволяет дочерним объектам определять свою позицию относительно родительского объекта или относительно соседних дочерних элементов (по идентификатору элемента).
В RelativeLayout дочерние элементы расположены так, что если первый элемент расположен по центру экрана, другие элементы, выровненные относительно первого элемента, будут выровнены относительно центра экрана. При таком расположении, при объявлении компоновки в XML-файле, элемент, на который будут ссылаться для позиционирования другие объекты, должен быть объявлен раньше, чем другие элементы, которые обращаются к нему по его идентификатору.
Если в программном коде мы не работаем с некоторыми элементами пользовательского интерфейса, создавать идентификаторы для них необязательно, однако определение идентификаторов для объектов важно при создании RelativeLayout. В компоновке RelativeLayout расположение элемента может определяться относительно другого элемента, на который ссылаются через его уникальный идентификатор:
android:layout_toLeftOf="@id/TextView1"
Давайте теперь создадим пример окна с корневой компоновкой RelativeLayout,
в котором будут семь элементов Button. В файле компоновки activity_main.xml напишите следующий код:
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_height="fill_parent" 
    android:layout_width="fill_parent"> 
 
    <Button 
        android:id="@+id/button_center" 
        android:text="Center" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_centerVertical="true" 
        android:layout_centerInParent="true"/> 
    <Button 
        android:id="@+id/button_bottom" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:text="Bottom" 
        android:layout_centerHorizontal="true" 
        android:layout_alignParentBottom="true"/> 
    <Button 
        android:id="@+id/button_top" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:text="Top" 
        android:layout_alignParentTop="true" 
        android:layout_centerHorizontal="true"/> 
    <Button 
        android:id="@+id/button_left" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:text="Left" 
        android:layout_alignParentLeft="true" 
        android:layout_centerVertical="true"/> 
    <Button 
        android:id="@+id/button_right" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:text="Right" 
        android:layout_alignParentRight="true" 
        android:layout_centerVertical="true"/> 
    <Button 
        android:id="@+id/button_rel_right" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_toLeftOf="@id/button_right" 
        android:layout_alignTop="@id/button_right" 
        android:text="RelRight"/> 
    <Button 
        android:id="@+id/button_rel_left" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_toRightOf="@id/button_left" 
        android:layout_alignTop="@id/button_left" 
        android:text="RelLeft"/> 
 
</RelativeLayout>
Кстати, обратите внимание, что атрибуты, которые обращаются к идентификаторам относительных элементов (например, layout_toLeftOf), используют синтаксис относительного ресурса @id/id. Внешний вид экрана с компоновкой RelativeLayout должен получиться таким:

Тип компоновки RelativeLayout применяется не так часто, как, например, LinearLayout, несмотря на то, что мастер создания проекта ее использует ее в качестве компоновки по умолчанию . Тем более что такое задание расположения элементов зависит от разрешения и ориентации экрана мобильного устройства. Если вы будете использовать RelativeLayout в собственных приложениях, всегда проверяйте внешний вид окна для различных разрешений и ориентации экрана, поскольку возможно наложение элементов друг на друга. В нашем случае, например, в вертикальной ориентации экрана кнопки Center и RelRight немного накладываются друг на друга:



Компоновка GridLayout

Компоновка GridLayout (сетка) — это относительно новая компоновка, появилась в версии 4.0 (API Level 14). Она похожа на TableLayout, но позволяет более гибко работать с  размерами ячеек и их расположением. В отличие от TableLayout, она не фиксирует дочерние элементы в TableRow, а использует атрибуты android:columnCount и android:rowCount для задания количества дочерних элементов соответственно в столбце или в строке сетки. Кроме того, в GridLayout можно объединять ячейки по горизонтали, используя атрибут android:layout_columnSpan, задавая им количество ячеек, которые должны быть объединены.
Для примера используем уже созданный набор кнопок из предыдущего урока, только поместим их в GridLayout и уберем элементы TableRow. Для кнопки "0" зададим атрибут android:layout_columnSpan="3", а для кнопки "*" — android:layout_columnSpan="2".
activity_main.xml
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_gravity="center" 
    android:columnCount="3" > 
    <Button 
        android:id="@+id/Button01" 
        android:layout_height="wrap_content" 
        android:layout_width="50dp" 
        android:text="1"/> 
    <Button 
        android:id="@+id/Button02" 
        android:layout_height="wrap_content" 
        android:layout_width="50dp" 
        android:text="2"/> 
    <Button 
        android:id="@+id/Button03" 
        android:layout_height="wrap_content" 
        android:layout_width="50dp" 
        android:text="3"/> 
    <Button 
        android:id="@+id/Button04" 
        android:layout_height="wrap_content" 
        android:layout_width="50dp" 
        android:text="4"/> 
    <Button 
        android:id="@+id/Button05" 
        android:layout_height="wrap_content" 
        android:layout_width="50dp" 
        android:text="5"/> 
    <Button 
        android:id="@+id/Button06" 
        android:layout_height="wrap_content" 
        android:layout_width="50dp" 
        android:text="6"/> 
    <Button 
        android:id="@+id/Button07" 
        android:layout_height="wrap_content" 
        android:layout_width="50dp" 
        android:text="7"/> 
    <Button 
        android:id="@+id/Button08" 
        android:layout_height="wrap_content" 
        android:layout_width="50dp" 
        android:text="8"/> 
    <Button 
        android:id="@+id/Button09" 
        android:layout_height="wrap_content" 
        android:layout_width="50dp" 
        android:text="9"/> 
    <Button 
        android:id="@+id/Button11" 
        android:layout_height="wrap_content" 
        android:layout_width="150dp" 
        android:layout_columnSpan="3" 
        android:text="0"/> 
    <Button 
        android:id="@+id/Button10" 
        android:layout_height="wrap_content" 
        android:layout_width="50dp" 
        android:layout_columnSpan="2" 
        android:text="*"/> 
    <Button 
        android:id="@+id/Button12" 
        android:layout_height="wrap_content" 
        android:layout_width="50dp" 
        android:text="#"/> 
</GridLayout>
Внешний вид компоновки на смартфоне:


Обратите внимание, что объединение ячеек автоматически не растягивает элемент, находящийся в них, как в случае с кнопкой "*". Размеры элемента в ячейке надо задавать отдельно. Для кнопки "0", которая растянута на 3 ячейки, кроме атрибута android:
layout_columnSpan мы изменили ширину кнопки
.

Компоновка TableLayout

Компоновка TableLayout позиционирует свои дочерние элементы в строки и столбцы. TableLayout не отображает линии обрамления для их строк, столбцов или ячеек. Кроме того, TableLayout может иметь строки с разным количеством ячеек. При формировании компоновки таблицы некоторые ячейки при необходимости можно оставлять пустыми.
При создании компоновки для строк используются объекты TableRow, которые являются дочерними классами TableLayout (каждый TableRow определяет единственную строку
в таблице). Строка может совсем не иметь ячеек или иметь одну и более ячеек, которые
являются контейнерами для других объектов View или ViewGroup. Ячейка может также быть объектом ViewGroup (например, допускается вложить другой TableLayout или LinearLayout как ячейку).
Для примера с использованием компоновки TableLayout можно создать окно, похожее на наборную панель телефона с 12 кнопками. В окне Layout Editor создайте TableLayout c четырьмя дочерними TableRow и двенадцатью кнопками, по три кнопки в каждой строке.
Для каждого элемента TableRow на вкладке Properties задайте свойства:

  • Layout height — wrap_content;
  • Layout width — wrap_content;
  • Gravity — center.

Свойство gravity задает выравнивание дочерних элементов в контейнере, в данном случае — по центру.
Для каждой кнопки на вкладке Properties задайте свойства:

  • Layout height — wrap_content;
  • Layout width — 70dp. Это фиксированная ширина элемента в dp (density-independent pixels) — независимые от плотности экрана пиксели. Подробнее о них поговорим в следующих уроках.

Надписи на кнопках сделайте так, как на телефонной клавиатуре (1, 2, 3, 4, 5, 6, 7, 8, 9, *, 0, #).
Файл компоновки должен получиться таким:
activity_main.xml
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/TableLayout01" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:gravity="center"> 
    <TableRow 
        android:id="@+id/TableRow01" 
        android:layout_height="wrap_content" 
        android:layout_width="wrap_content" 
        android:gravity="center"> 
        <Button 
            android:id="@+id/Button01" 
            android:layout_height="wrap_content" 
            android:text="1" 
            android:layout_width="70dp"/> 
        <Button 
            android:id="@+id/Button02" 
            android:layout_height="wrap_content" 
            android:text="2" 
            android:layout_width="70dp"/> 
        <Button 
            android:id="@+id/Button03" 
            android:layout_height="wrap_content" 
            android:text="3" 
            android:layout_width="70dp"/> 
    </TableRow> 
    <TableRow 
        android:id="@+id/TableRow02" 
        android:layout_height="wrap_content" 
        android:layout_width="wrap_content" 
        android:gravity="center"> 
        <Button 
            android:id="@+id/Button04" 
            android:layout_height="wrap_content" 
            android:layout_width="70dp" 
            android:text="4"/> 
        <Button 
            android:id="@+id/Button05" 
            android:layout_height="wrap_content" 
            android:layout_width="70dp" 
            android:text="5"/> 
        <Button 
            android:id="@+id/Button06" 
            android:layout_height="wrap_content" 
            android:layout_width="70dp" 
            android:text="6"/> 
    </TableRow> 
    <TableRow 
        android:id="@+id/TableRow03" 
        android:layout_height="wrap_content" 
        android:layout_width="wrap_content" 
        android:gravity="center"> 
        <Button 
            android:id="@+id/Button07" 
            android:layout_height="wrap_content" 
            android:layout_width="70dp" 
            android:text="7"/> 
        <Button 
            android:id="@+id/Button08" 
            android:layout_height="wrap_content" 
            android:layout_width="70dp" 
            android:text="8"/> 
        <Button 
            android:id="@+id/Button09" 
            android:layout_height="wrap_content" 
            android:layout_width="70dp" 
            android:text="9"/> 
    </TableRow> 
    <TableRow 
        android:id="@+id/TableRow04" 
        android:layout_height="wrap_content" 
        android:layout_width="wrap_content" 
        android:gravity="center"> 
        <Button 
            android:id="@+id/Button10" 
            android:layout_height="wrap_content" 
            android:layout_width="70dp" 
            android:text="*"/> 
        <Button 
            android:id="@+id/Button11" 
            android:layout_height="wrap_content" 
            android:layout_width="70dp" 
            android:text="0"/> 
        <Button 
            android:id="@+id/Button12" 
            android:layout_height="wrap_content" 
            android:layout_width="70dp" 
            android:text="#"/> 
    </TableRow> 
</TableLayout>
В результате внешний вид экрана должен получиться в виде телефонной клавиатуры:



Компоновка TableLayout на практике применяется довольно редко, обычно вместо нее используют сочетание компоновок LinearLayout или GridLayout, которая будет рассмотрена далее. Компоновку TableLayout удобно использовать, если расположение элементов представлено в виде "таблицы", как в нашем примере. Кроме того, существует компоновка GridLayout, которая внешне аналогична TableLayout, но имеет дополнительные возможности. Ее мы рассмотрим в следующем уроке.