5. Работа виджетами из Activity

Снова про root класс для всех виджетов.

View

Android SDK включает множество виджетов, которые являются дочерним классом класса View. Таким образом, каждый виджет является экземпляром класса View, как и отражено на рисунке ниже.

alt text

Рис. 1. Иерархия класса View. Источник изображения.

Создание нового Activity

Для начала, создадим новое Activity, в котором будем создавать виджеты и работать из Activity.

alt text

Рис. 2. Создание нового Activity.

Далее, вам откроется окно с настройками нового Activity. Необходимо ввести имя и поставить галочку на автоматическое создание файла layout для Activity.

alt text

Рис. 3. Настройка нового Activity.

Замем вы увидите изменения в структуре проекта: добавится файл с кодом имя_класса.kt, появится к нему файл имя_layout.xml. Также, не мало важным является добавление Activity в файл AndroidManifest.xml, который является основой вашего проекта.

Содержание файла AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Android_notes"
        tools:targetApi="31">
        <activity
            android:name=".activities.ViewExamples"
            android:exported="false" />
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Где мы можем увидеть наше новое Activity в списке проекта.

Переход между Activity (Intent, вкратце)

В рамках “удобства” по работе с несколькими Activity рассмотрим небольшой пример работы класса Intent

Intent — это абстрактное описание операции, которая должна быть выполнена. Его можно использовать с startActivity для запуска Activity, broadcastIntent для отправки его любым заинтересованным компонентам BroadcastReceiver и Context.startService(Intent) или Context.bindService(Intent, BindServiceFlags, Executor, ServiceConnection) для связи с фоновой службой Service.

Для начала, нам понадобится только метод startActivity(). Добавим переход на другое Activity при помощи Button во время нажатия (setOnClickListener). Добавим кнопку в файле activity_имя.xml:

<Button
    android:id="@+id/bViews"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Views" />

Инициализируем кнопку в коде ИМЯ_Activity.kt, выделяя память под кнопку в методе onCreate(), инициализируя обработчик нажатия на кнопку в методе onResume() (когда Activity уже видна пользователю):

class MainActivity : AppCompatActivity() {

    private lateinit var bViewExamples: Button

    // onCreate() – вызывается при первом создании Activity
    override fun onCreate(savedInstanceState: Bundle?) {

        ...
        ...
        bViewExamples = findViewById<Button>(R.id.bViews)
    }

    override fun onResume() {
        super.onResume()
        bViewExamples.setOnClickListener({
            val randomIntent = Intent(this, ViewExamples::class.java)
            startActivity(randomIntent)
        });
    }

Из обработчика нажатия мы видим создание экземпляра класса Intent, используя конструктор public Intent(Context packageContext, Class<?> cls):

val randomIntent = Intent(this, ViewExamples::class.java)
startActivity(randomIntent)

Согласно документации аргументами функции являются:

Создание `Intent` для определенного компонента.  Это обеспечивает удобный способ создания `Intent`, которое предназначено для выполнения `hard-coded` класса.

Params:
packageContext – A Context of the application package implementing this class. 
cls – The component class that is to be used for the intent.

Первый параметр – это Context. Activity является подклассом Context, можем использовать запись ИМЯ_КЛАССА_В_КОТОРОМ_НАХОДИМСЯ.this, или укороченную запись this.

Метод startActivity(randomIntent) выполняет переход на необходимый нам класс, т.е. Activity.

Виджеты (Views)

findViewById()

Метод findViewById() возвращает объект класса View по его идентификатору на разметке (какой то из виджетов, например кнопку). Теперь, имея данный экземпляр виджета, вы можете вызывать реализованные для него методы, такие как изменение размеров, цвета, текста и т.п. Метод работает таким образом, что получает этот объект из предварительно подготовленного через инфлейт (парсинг разметки) и сгенерированного на его основе класса R нужный нам виджет из дерева объектов отображаемых на экране.

TextView

Инициализация

В рамках .xml-layout’а добавляем след. образом:

    <TextView
        android:id="@+id/textView"
        android:layout_width="130dp"
        android:layout_height="0dp"
        android:layout_marginStart="20dp"
        android:layout_marginBottom="579dp"
        android:text="TextView"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button_back_to_main" />

В коде Kotlin мы должны воспользоваться классом TextView, импортировав его из import android.widget.TextView.

Инициализация в коде и работа с конкретным обхъектом View происходит при помощи метода findVewiById():

private lateinit var tvView_01: TextView
tvView_01 = findViewById(R.id.textView)

Атрибуты

Программное изменение текста

Программно можно изменить наполнение TextView при помощи метода класса: setText(CharSequence text):

tvView_01.setText("Hello from Code")

Изменение размера текста

Приведем лишь 2 примера с установлением размера текста:

// COMPLEX_UNIT_PX - Value is raw pixels                
tvView_01.setTextSize(TypedValue.COMPLEX_UNIT_PX, 10F)  
// COMPLEX_UNIT_DIP - Value is Device Independent Pixels
tvView_01.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20F) 

Остальные возможные типы значений размера текста можно увидеть в классе TypedValue.java:

    /** complex unit: Value is raw pixels. */
    public static final int COMPLEX_UNIT_PX = 0;
    /** complex unit: Value is Device Independent Pixels. */
    public static final int COMPLEX_UNIT_DIP = 1;
    /** complex unit: Value is a scaled pixel. */
    public static final int COMPLEX_UNIT_SP = 2;
    /** complex unit: Value is in points. */
    public static final int COMPLEX_UNIT_PT = 3;
    /** complex unit: Value is in inches. */
    public static final int COMPLEX_UNIT_IN = 4;
    /** complex unit: Value is in millimeters. */
    public static final int COMPLEX_UNIT_MM = 5;

Изменение цвета текста

tvView_01.setTextColor(Color.rgb(255,192,0))    

alt text

Возможность нажать на TextView

Если вы хотите, чтобы TextView обрабатывал нажатия (атрибут android:onClick), то не забывайте также использовать в связке атрибут android:clickable="true" (в файле layout/*.xml). Иначе работать не будет!

// Возможность нажать на кнопку                           
tvView_01.setOnClickListener({                             
  tvView_01.setTextColor(Color.rgb(55,12,0))              
})                                                         

Меняем цвет текста при нажатии на TextView.

alt text

Button

Наследуется от TextViewи является базовым классом для класса СompoundButton. От класса CompoundButton в свою очередь, наследуются такие элементы как CheckBox, ToggleButton и RadioButton. В Android для кнопки используется класс android.widget.Button. На кнопке располагается текст и на кнопку нужно нажать, чтобы получить результат.

Инициализация

В рамках .xml-layout’а добавляем след. образом:

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="99dp"
        android:text="Button"
        app:layout_constraintBottom_toBottomOf="@+id/textView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/textView" />

Три способа обработать нажатие на кнопку

Первый, атрибут - onClick

Добавляем указатель на нашу функцию обработки нажатия на кнопку в атрибуты Button:

android:onClick="customOnClick"

В коде добавим функцию:

fun customOnClick(v: View?){
    bExample.setText("1st method")
}

Второй, метод - setOnClickListener()

В данном случае можно задать обработку нажатия для конкретной кнопки отдельно:

bExample2.setOnClickListener({
    bExample2.setText("2nd method")
})

Третий, интерфейс - OnClickListener()

В этом случае необходимо сначала добавить интерфейс View.OnClickListener к текущему классу, затем override метод обработки нажатий onClick для всех кнопок текущего класса Activity:

class ViewExamples : AppCompatActivity(), View.OnClickListener {

    override fun onCreate(savedInstanceState: Bundle?) {...}

    override fun onClick(v: View?){
        bExample3.setText("3dr method")
    }
}

Далее, можем указать обработчику на интерфейс текущего класса:

bExample3.setOnClickListener(this)

alt text

SeekBar (Слайдер)