Intencje jawne: Trzy aktywności
Tworzymy projekt, w którym będziemy mogli wykorzystać trzy osobne okna aktywności. Jedno z okien jest oknem głównym, pozostałe dwa są oknami podrzędnymi. Dodanie nowych aktywności w obrębie jednego projektu można wykonać po wybraniu New/ Activity/ Empty Activity
Ustaw nazwę okna aktywności i język (Kotlin)
Po dodaniu mamy trzy aktywności:
- MainActivity (przyjmujemy że jest główna)
- Okno1
- Okno2
Prawidłowo dodane aktywności do projektu są zainicjowane w manifeście tworzonej aplikacji. Sprawdź czy manifest aplikacji zawiera odpowiednie wpisy. Patrz poniższy kod
Wskazówka:
<?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.IntencjaAktywnosci"
tools:targetApi="31">
<activity
android:name=".Okno1"
android:exported="false" />
<activity
android:name=".Okno2"
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>
Pliki XML układu tworzonych aktywności
Zadaniem tworzonej aplikacji jest możliwość przechodzenia pomiędzy aktywnością główną (okno główne) do aktywności podrzędnych (okno 1, okno 2) oraz przejścia pomiędzy aktywnościami podrzędnymi.
Do projektu dodajemy trzy pliki XML widoku układu aktywności. Aktywności powinny zawierać po jednym polu tekstowym i po trzy komponenty Button dla aktywności głównej i po dwa komponenty Button dla aktywności podrzędnych. Poniżej proponowany układ komponentów w widokach aktywności.
Dodając komponenty do aktywności zadbaj o to aby każdy z osadzanych komponentów miał inny identyfikator. Przykładowa zawartość pliku XML układu aktywności dla drugiego okna.
Wskazówka:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Okno2">
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="160dp"
android:layout_marginTop="64dp"
android:layout_marginEnd="160dp"
android:text="Okno 2"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="160dp"
android:layout_marginTop="83dp"
android:layout_marginEnd="160dp"
android:text="Otwórz Okno 1"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView3" />
<Button
android:id="@+id/button7"
android:layout_width="232dp"
android:layout_height="76dp"
android:layout_marginStart="160dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="160dp"
android:text="Otwórz Okno główne"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.503"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button6" />
</androidx.constraintlayout.widget.ConstraintLayout>
Otwarcie innej aktywności
Otwarcie innej aktywności zrealizujemy przez funkcję osadzoną w słuchaczu zdarzeń kliknięcia w kontrolke Button (setOnClickListener). Funkcja odpowiedzialna za wywołanie nowej intencji to startActivity(). Jej parametrem w najprostszym wywołaniu jest intencja o uruchamianej nowej aktywności.
Przejdź do głównego pliku tworzonej aplikacji i wprowadź poniższy kod
Wskazówka:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val bt1=findViewById<Button>(R.id.button1)
bt1.setOnClickListener {
val intencja =Intent(this,Okno1::class.java)
startActivity(intencja)
}
}
Uruchom aplikację i sprawdź efekt działania. Prawidłowo działająca aplikacja pozwala otworzyć drugą aktywność o nazwie Okno 1. Patrz poniższa ilustracja
Uruchamianie aktywności z klasy zewnętrznej
Aby nie powielać kodu, tworzone funkcje zapiszemy w osobnej klasie. W tym celu przejdź do hierarchii widoku projektu. Z menu prawego klawisza myszki wybierz New/ Kotlin Class. Klasę nazwij MojeFunkcje.
Do pliku wprowadź poniższy kod, który zawiera funkcję zamykającą aplikację oraz funkcje otwierającą nową aktywność podaną w parametrze.
Wskazówka:
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.core.content.ContextCompat.startActivity
class MojeFunkcje {
fun Zamknij(aktywnosc:Activity){
//finishAffinity- zamyka wszystkie aktywności
//finish- zamyka biezaca aktywność z której
// funkcja została wywołana
aktywnosc.finishAffinity()
System.exit(0)
}
fun OtworzAktywnosc(kontekst: Context, klasaAktywnosci: Class<*>){
val intencja = Intent(kontekst,klasaAktywnosci )
//Bundle.EMPTY - twórz nowy pusty pakiet
startActivity(kontekst,intencja, Bundle.EMPTY)
}
}
W pliku głównym (MainActivity.kt) tworzonej aplikacji deklarujemy zmienną opartą na klasie zbioru utworzonych funkcji. Deklarację poprzedzamy słowem kluczowym lateinit. Instrukcja oznacza, że kompilator wstrzymuje się z wstępnym przypisaniem wartości dla zmiennej. W tym przypadku zostaje to zrobione w metodzie onCreate(). Tak zainicjowana zmienna jest publiczna i jest dostępna w innych później inicjowanych klasach projektu rozwiązania.
Wskazówka:
lateinit var mojeFunkcje: MojeFunkcje
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
mojeFunkcje=MojeFunkcje()
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Dopisujemy kod obsługi słuchaczy OnClick dla komponentów klawiszy otwarcia aktywności dla Okna 2 i zamknięcia aplikacji.
Wskazówka:
val bt2=findViewById<Button>(R.id.button2)
bt2.setOnClickListener {
mojeFunkcje.OtworzAktywnosc(this,Okno2::class.java)
}
val bt3=findViewById<Button>(R.id.button3)
bt3.setOnClickListener {
mojeFunkcje.Zamknij(this)
}
Skompiluj program i sprawdź efekty działania. Prawidłowo działająca aplikacja pozwala otworzyć okna obu aktywności i zamknąć aplikację.
Obsługa aktywności podrzędnych
Obie aktywności podrzędne mają ten sam układ widoku i chcemy aby z każdej z nich można było uruchomić inna aktywność podrzędną oraz przejść do głównej aktywności. Kody obu aktywności są prawie jednakowe. Różnią się parametrami podanymi przy otwarciu nowej aktywności.
Kod klasy aktywności dla Okna 1
Wskazówka:
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
class Okno1 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_okno1)
val bt4=findViewById<Button>(R.id.button4)
bt4.setOnClickListener {
//otwórz nową aktywność- Okno 2
mojeFunkcje.OtworzAktywnosc(this,Okno2::class.java)
}
val bt5=findViewById<Button>(R.id.button5)
bt5.setOnClickListener {
//otwórz nową aktywność- Okno Główne
mojeFunkcje.OtworzAktywnosc(this,MainActivity::class.java)
}
}
}
Kod klasy aktywności dla Okna 2
Wskazówka:
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
class Okno2 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_okno2)
val bt6=findViewById<Button>(R.id.button6)
bt6.setOnClickListener {
//otwórz nową aktywność- Okno 1
mojeFunkcje.OtworzAktywnosc(this,Okno1::class.java)
}
val bt7=findViewById<Button>(R.id.button7)
bt7.setOnClickListener {
//otwórz nową aktywność- Okno Główne
mojeFunkcje.OtworzAktywnosc(this,MainActivity::class.java)
}
}
}
Skompiluj program i sprawdź jak zachowuje się utworzona aplikacja.
Prawidłowo działająca aplikacja pozwala przechodzić po każdej z aktywności podrzędnej i wracać do głównej.
Kody
Zawartość pliku głównej aktywności
Wskazówka:
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
lateinit var mojeFunkcje: MojeFunkcje
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
mojeFunkcje=MojeFunkcje()
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val bt1=findViewById<Button>(R.id.button1)
bt1.setOnClickListener {
val intencja =Intent(this,Okno1::class.java)
startActivity(intencja)
}
val bt2=findViewById<Button>(R.id.button2)
bt2.setOnClickListener {
mojeFunkcje.OtworzAktywnosc(this,Okno2::class.java)
}
val bt3=findViewById<Button>(R.id.button3)
bt3.setOnClickListener {
mojeFunkcje.Zamknij(this)
}
}
}
Zawartość pliku klasy MojeFunkcje.kt
Wskazówka:
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.core.content.ContextCompat.startActivity
class MojeFunkcje {
fun Zamknij(aktywnosc:Activity){
//finishAffinity- zamyka wszystkie aktywności
//finish- zamyka biezaca aktywność z której
// funkcja została wywołana
aktywnosc.finishAffinity()
System.exit(0)
}
fun OtworzAktywnosc(kontekst: Context, klasaAktywnosci: Class<*>){
val intencja = Intent(kontekst,klasaAktywnosci )
//Bundle.EMPTY - twórz nowy pusty pakiet
startActivity(kontekst,intencja, Bundle.EMPTY)
}
Zawartość pliku aktywności podrzędnej Okno1.kt
Wskazówka:
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
class Okno1 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_okno1)
val bt4=findViewById<Button>(R.id.button4)
bt4.setOnClickListener {
//otwórz nową aktywność- Okno 2
mojeFunkcje.OtworzAktywnosc(this,Okno2::class.java)
}
val bt5=findViewById<Button>(R.id.button5)
bt5.setOnClickListener {
//otwórz nową aktywność- Okno Główne
mojeFunkcje.OtworzAktywnosc(this,MainActivity::class.java)
}
}
}
Zawartość pliku aktywności podrzędnej Okno2.kt
Wskazówka:
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
class Okno2 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_okno2)
val bt6=findViewById<Button>(R.id.button6)
bt6.setOnClickListener {
//otwórz nową aktywność- Okno 1
mojeFunkcje.OtworzAktywnosc(this,Okno1::class.java)
}
val bt7=findViewById<Button>(R.id.button7)
bt7.setOnClickListener {
//otwórz nową aktywność- Okno Główne
mojeFunkcje.OtworzAktywnosc(this,MainActivity::class.java)
}
}
}
Zawartość manifestu
Wskazówka:
<?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.IntencjaAktywnosci"
tools:targetApi="31">
<activity
android:name=".Okno1"
android:exported="false" />
<activity
android:name=".Okno2"
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>