Rozwiązania. Arkusz egzaminacyjny INF.04 czerwiec 2022
INF 04 egzamin praktyczny Rozwiązanie arkusza czerwiec 2022Część I. Aplikacja konsolowa
Napisz program implementujący algorytm przeszukiwania tablicy z wartownikiem. Opis algorytmu znajduje się w poniżej.
By odnaleźć element x podejmiemy następujące kroki:
- na końcu tablicy (pod indeksem n+1) wstawimy szukany element x - będzie to nasz wartownik, w przypadku, gdy nie znajdziemy go nigdzie indziej w tablicy, zabezpieczy nas on przed wyjściem poza tablicę,
- przejdziemy po kolejnych elementach tablicy, tak długo aż nie znajdziemy szukanego elementu,
- w momencie znalezienia szukanego elementu x sprawdzamy, który jest to element tablicy? Jeżeli jest to ostatni element tablicy (n+1) to trafiliśmy na naszego wartownika i oznacza to, że w tablicy nie było szukanego elementu x, w przeciwnym razie element x został odnaleziony.
Założenia do programu:
- Program wykonywany w konsoli.
- Zastosowany obiektowy język programowania zgodny z zainstalowanym na stanowisku egzaminacyjnym: C++ lub C#, lub Java, lub Python.
- Przeszukiwana jest minimum 50 elementowa tablica liczb całkowitych wypełniona wartościami pseudolosowymi z zakresu od 1 do 100.
- Wyszukiwane jest pierwsze wystąpienie elementu w tablicy.
- Wypełnianie tablicy i przeszukiwanie jest realizowane w oddzielnych funkcjach / metodach. Funkcja przeszukująca zwraca indeks odnalezionego elementu.
- Wartość do wyszukania jest pobierana z klawiatury.
- Po przeszukaniu tablicy na ekranie wyświetlana jest zawartość tablicy (liczby oddzielone przecinkami) oraz indeks, pod którym odszukano wartość lub w przypadku jej braku ? stosowny komunikat.
- Program powinien podejmować zrozumiałą komunikację z użytkownikiem, dane wprowadzane i wyprowadzane powinny być opatrzone zrozumiałym opisem.
- Program powinien być zapisany czytelnie, z zachowaniem zasad czystego formatowania kodu, należy stosować znaczące nazwy zmiennych i funkcji.
- Program główny powinien zawierać test działania aplikacji.
Podejmij próbę kompilacji i uruchomienia aplikacji. Informacje dotyczące dokumentacji i zrzutów ekranowych umieszczono w części III zadania. Kod aplikacji przygotuj do nagrania na płytę. W podfolderze konsola powinno znaleźć się archiwum całego projektu o nazwie konsola.zip, plik z kodem źródłowym programu oraz plik uruchomieniowy, jeżeli istnieje.
Część II. Aplikacja mobilna
Wykonaj aplikację mobilną za pomocą środowiska programistycznego dostępnego na stanowisku egzaminacyjnym oraz uruchom ją w dostępnym emulatorze systemu mobilnego. Aplikacja jest fragmentem programu do przeglądania ofert turystycznych. Do wykonania aplikacji należy wykorzystać obraz z archiwum zad1.zip znajdującego się na pulpicie konta Egzamin i zabezpieczonego hasłem: !Turystyk@
Źródło CKE
Na obrazie 1a przedstawiono stan po uruchomieniu aplikacji mobilnej. W zależności od zastosowanego środowiska programistycznego oraz emulowanego systemu wynik końcowy może nieznacznie się różnić od przedstawionego. Na obrazie 1b przedstawiono zachowanie aplikacji: 5 razy wciśnięto przycisk POLUB i w efekcie status pod przyciskami wyświetla tekst 5 polubień.
Elementy aplikacji:
- Tytuł o treści: Domek w górach.
- Obraz o nazwie obraz.jpg wypakowany z archiwum.
- Trzy przyciski o treści: POLUB, USUŃ, ZAPISZ umiejscowione obok siebie.
- Napis o treści 0 polubień.
- Linia horyzontalna.
- Napis o treści Opis.
- Napis o treści Odwiedź komfortowy domek w Sudetach, blisko do szlaków turystycznych.
Działanie aplikacji:
- Aplikacja implementuje licznik polubień, który w stanie początkowym aplikacji jest równy 0, następnie jego stan jest:
- inkrementowany po wciśnięciu przycisku POLUB,
- dekrementowany po wciśnięciu przycisku USUŃ. Licznik nie może być niższy niż 0.
- Stan licznika jest wyświetlany pod przyciskami, w formie napisu <x> polubień, gdzie <x> oznacza aktualną wartość licznika.
Założenia aplikacji:
- Interfejs użytkownika zapisany za pomocą języka znaczników wspieranego w danym środowisku (np. XAML, XML).
- Zastosowany typ rozkładu liniowy wertykalny (Linear / Stack lub inny o tej idei) z zagłębionym rozkładem liniowym horyzontalnym dla przycisków.
- Margines wewnętrzny górny dla całej strony lub rozkładu wertykalnego: 20 px (lub dp)
- Kolor tła przycisków i rozkładu, w którym się znajdują: Teal (#008080), zgodnie z Obrazem 1a. Kolory czcionki: biały dla przycisków oraz Gray (#808080) dla napisu Odwiedź..., zgodnie z Obrazem 1a.
- Czcionka tytułu ma rozmiar największy spośród użytych w aplikacji.
- Czcionka napisu Opis jest pogrubiona.
- Napis o liczbie polubień jest wyrównany do prawej.
- Obraz wypełnia całą szerokość strony (zależnie od zastosowanego aspektu może być automatycznie obcięty przez emulator ? zobacz obraz 1b).
- Linia horyzontalna jest koloru Gray (#808080), dopuszcza się również prostokąt o wysokości 1.
- Aplikacja powinna być zapisana czytelnie, z zachowaniem zasad czystego formatowania kodu, należy stosować znaczące nazwy zmiennych i funkcji.
Podejmij próbę kompilacji i emulacji. Informacje dotyczące dokumentacji i zrzutów ekranowych umieszczono w części III zadania.
Kod aplikacji przygotuj do nagrania na płytę. W podfolderze mobilna powinno znaleźć się archiwum całego projektu o nazwie mobilna.zip, plik źródłowy interfejsu użytkownika (XAML lub XML) oraz plik źródłowy kodu skojarzonego z interfejsem użytkownika.
Część III. Dokumentacja aplikacji
Wykonaj dokumentację do aplikacji utworzonych na egzaminie. W kodzie źródłowym aplikacji konsolowej utwórz nagłówek funkcji przeszukującej, według wzoru zgodnie z listingiem 1. Nagłówek powinien znaleźć się w kodzie źródłowym nad funkcją. W miejscu nawiasów <> należy podać nazwę funkcji, nazwy argumentów wraz z krótkim opisem, typ zwracany wraz z krótkim opisem, krótki opis zawierający przynajmniej nazwę algorytmu. Gdy funkcja nie ma argumentów ? zapisać ?brak?. W miejscu autor należy podać swój numer.
UWAGA: Dokumentację umieścić w komentarzu (wieloliniowym lub kilku jednoliniowych). Znajdujący się w listingu 1 wzór dokumentacji jest bez znaków początku i końca komentarza, gdyż te są różne dla różnych języków programowania
Listing 1. Wzór dokumentacji funkcji
Źródło CKE
Wykonaj zrzuty ekranu dokumentujące uruchomienie aplikacji utworzonych podczas egzaminu. Zrzuty powinny obejmować cały obszar ekranu monitora z widocznym paskiem zadań. Jeżeli aplikacja uruchamia się, na zrzucie należy umieścić okno z wynikiem działania programu oraz otwarte środowisko programistyczne z projektem lub okno terminala z kompilacją projektu. Jeżeli aplikacja nie uruchamia się z powodu błędów kompilacji, należy na zrzucie umieścić okno ze spisem błędów i widocznym otwartym środowiskiem programistycznym. Wykonać należy tyle zrzutów ile interakcji podejmuje aplikacja. Wymagane zrzuty ekranu:
- Aplikacja konsolowa: dowolna liczba zrzutów nazwanych konsola1, konsola2 ...
- Aplikacja mobilna: dowolna liczba zrzutów nazwanych mobile1, mobile2 ... (np. stan początkowy, po wciśnięciu przycisku polubień)
W edytorze tekstu pakietu biurowego utwórz plik z dokumentacją i nazwij go egzamin. Dokument powinien zawierać podpisane zrzuty ekranu oraz zapisane informacje:
- Nazwę systemu operacyjnego, na którym pracował zdający.
- Nazwy środowisk programistycznych, z których zdający korzystał na egzaminie.
- Nazwy języków programowania.
- Nazwa emulatora systemu mobilnego.
Zrzuty ekranu i dokument umieść w podfolderze dokumentacja.
Rozwiązanie części I: aplikacja konsolowa. Przeszukiwanie z wartownikiem
Przygotowanie rozwiązani rozpoczniemy od wybrania w kompilatorze Visual Studio modułu kompilacji dla Aplikacja konsoli (.NET Framework)
Definiujemy zmienne
Do działania programu będziemy potrzebować kilku zmiennych- rozmiaru tablicy podanej przez użytkownika, tablicy jednowymiarowej oraz generatora liczb losowych. Inicjujemy te zmienne jak poniżej
Wskazówka:
using System;
namespace czerwiec_2022_problem_1_przeszukiwanie_z_wartownikiem
{
internal class Program
{
//rozmiar tablicy
static int n = 0;
//jednowymiarowa tablica danych liczb całkowitych
static int[] tab;
//zmienna generatora losowego
static Random los = new Random();
static void Main(string[] args)
{
}
}
}
Funkcja generująca tablicę danych
Zgodnie z warunkami zadania piszemy kod funkcji generującej losowe dane tablic. Jednocześnie w tej funkcji poprosimy użytkownika o podani rozmiaru tablicy. Rozmiar tablicy jaką utworzymy będzie o jeden większy niż podany. Ponieważ na ostatnim indeksie umieścimy wartownika. Czyli szukaną liczbę
Wskazówka:
static void RobTablice()
{
//odczytaj rozmiar tablicy podany z klawiatury
Console.Write("Podaj rozmiar tablicy nie mniejszy niż 50, n=");
n=int.Parse(Console.ReadLine());
//zrób tablicę o rozmiarze większym o 1, będzie to indeks wartownika
tab = new int[n+1];
//wypełnij wartościami losowymi
//w warunkach zadania nie jest podane
//czy losowe wartości nie mogą się powtarzać
//losujemy najłatwiej z mozliwymi powtórzeniami
for(int i = 0; i < n; i++)
tab[i] = los.Next(100)+1;
}
Funkcja szukająca
Funkcja szukająca ma zwracać indeks szukanego elementu. Jeżeli będzie to indeks wartownika, to oznacza, że szukanej wartości w podanym zbiorze danych nie ma. Argumentem naszej funkcji jest szukana wartość liczbowa.
Wskazówka:
static int Szukaj(int szukana)
{
//wstaw wartownika na ostatni indeks tablicy
tab[n] = szukana;
//szukaj, jak znalazłes to wyskocz z pętli
//i podaj pierwszy indeks wystąpienia szukanej wartości
for(int i = 0;i<n+1; i++)
if (tab[i] == szukana) return i;
//jak nie znalezłeś to zwróć indeks wartownika
return n;
}
Funkcja zwracająca komunikat wyniku
Ostatnia funkcja do napisania to funkcja zwracająca wynik. Będzie to funkcja dwuargumentowa. Argumentami to szukana wartość oraz indeks zwrócony przez funkcję Szukaj.
Wskazówka:
static void PokazTablice_i_Wynik_Szukania(int x,int id)
{
for(int i=0;i<n+1;i++)
Console.Write(String.Format("{0},", tab[i]));
//komunikat gdy znaleziono
if (id != n)
Console.WriteLine(String.Format("\nSzukana liczba {0} jest na indeksie {1}", x, id));
else
Console.WriteLine(String.Format("\nSzukana liczba {0} nie została znaleziona.
Znaleziono wartownika na indeksie {1}", x, id));
}
Kod głównej funkcji programu
W kodzie głównej funkcji Main uruchamiamy powyższe funkcje z przesłaniem wartości podanych z klawiatury
Wskazówka:
static void Main(string[] args)
{
Console.WriteLine("Witaj w CzD! Wyszukiwanie z wartownikiem.
Egzamin INF.04 czerwiec 2022");
RobTablice();
Console.Write("Podaj szukaną liczbę całkowitą x = ");
int x = int.Parse(Console.ReadLine());
int id = Szukaj(x);
PokazTablice_i_Wynik_Szukania(x,id);
Console.ReadKey();
}
Testujemy działanie aplikacji. Sprawdzamy wartownika. Podamy rozmiar tablicy na bardzo mały (tu 5) i dowolną wartość liczbową do odszukania. Może udam nam się nie trafić
Wykonujemy drugi test na duży rozmiar tablicy zgodny warunkami zadania egzaminacyjnego
Pełny kod rozwiązania
Wskazówka:
using System;
namespace czerwiec_2022_problem_1_przeszukiwanie_z_wartownikiem
{
internal class Program
{
//rozmiar tablicy
static int n = 0;
//jednowymiarowa tablica danych liczb całkowitych
static int[] tab;
//zmienna generatora losowego
static Random los = new Random();
static void RobTablice()
{
//odczytaj rozmiar tablicy podany z klawiatury
Console.Write("Podaj rozmiar tablicy nie mniejszy niż 50, n=");
n=int.Parse(Console.ReadLine());
//zrób tablicę o rozmiarze większym o 1, będzie to indeks na wartownika
tab = new int[n+1];
//wypełnij wartościami losowymi
//w warunkach zadania nie jest podane
//czy losowe wartości nie mogą się powtarzać
//losujemy najłatwiej z mozliwymi powtórzeniami
for(int i = 0; i < n; i++)
tab[i] = los.Next(100)+1;
}
static int Szukaj(int szukana)
{
//wstaw wartownika na ostatni indeks tablicy
tab[n] = szukana;
//szukaj, jak znalazłes to wyskocz z pętli
//i podaj pierwszy indeks wystąpienia szukanej wartości
for(int i = 0;i<n+1; i++)
if (tab[i] == szukana) return i;
//jak nie znalezłeś to zwróć indeks wartownika
return n;
}
static void PokazTablice_i_Wynik_Szukania(int x,int id)
{
for(int i=0;i<n+1;i++)
Console.Write(String.Format("{0},", tab[i]));
//komunikat gdy znaleziono
if (id != n)
Console.WriteLine(String.Format("\nSzukana liczba {0}
jest na indeksie {1}", x, id));
else
Console.WriteLine(String.Format("\nSzukana liczba {0}
nie została znaleziona.
Znaleziono wartownika na indeksie {1}", x, id));
}
static void Main(string[] args)
{
Console.WriteLine("Witaj w CzD!
Wyszukiwanie z wartownikiem.
Egzamin INF.04 czerwiec 2022");
RobTablice();
Console.Write("Podaj szukaną liczbę całkowitą x = ");
int x = int.Parse(Console.ReadLine());
int id = Szukaj(x);
PokazTablice_i_Wynik_Szukania(x,id);
Console.ReadKey();
}
}
}
Rozwiązanie część II. Aplikacja mobilna: Przeglądanie ofert turystycznych
UWAGA. Do rozwiązania użyto języka Kotlin. Ponadto jest potrzebny plik graficzny z podanych materiałów egzaminacyjnych. W dalszej treści znajdziesz link do pobrania.
Inicjujemy pusty projekt
Otwieramy kompilator Android Studio i wybieramy New Project/ Empty Views Activity. Wybór zatwierdzamy klawiszem Next.
Ustalamy nazwę projektu aplikacji, folder lokalizacji projektu i wybieramy język. Omawiane rozwiązanie jest pisane w Kotlinie, stąd wybierz jak poniżej.
Projekt jest gotowy do wprowadzania kodu, ale zanim zaczniesz kodować, przygotuj wirtualny emulator urządzenia mobilnego.
Przygotowujemy emulator urządzenia mobilnego.
Zauważ, że w arkuszu egzaminacyjnym przegotowanym przez CKE jedna z ilustracji przedstawia działanie aplikacji na urządzeniu Nexus 5X API 29 x86. Jeżeli taki emulator istnieje w twoim kompilatorze to go uruchom. Jeżeli nie, to nie próbuj instalować urządzenia emulatora- masz odcięty Internet. Wybierz dowolny emulator z API 29 lub nowszym API (wyższy numer).
Jeżeli nie masz przygotowanego emulatora urządzenia mobilenego i nie wiesz jak to zrobić, to przejdź do tej instrukcji: Jak zainstalować emulator ?
Układ widoku
Przygotowujemy główny widok aktywności aplikacji. Cały układ widoku standardowo jest zapisywany w pliku XML w lokalizacji app/res/layout/activity_main.xml. Zostawiamy proponowane nazwy- szkoda czasu na egzaminie na ich zmianę. Ponadto osobom sprawdzającym kod łatwiej jest się poruszać po projekcie ze standardowymi nazwami i lokalizacjami plików.
Usuwamy standardową kontrolkę TextView i osadzamy LinearLayout (vertical)
Kliknij tak jak pokazuje to ponizszy rysunek, aby własciwości layout_width oraz layout_height przyjęły wartości 0dp.
Pozwoli to aby LinearLayout (vertical) skalował się do różnych rozdzielczości ekranów z zachowanym marginesem 20dp.
W zakładce Attributes ustawiamy margines dla osadzonej kontrolki LinearLayout. Parametry marginesu to 20dp (tak podaje arkusz egzaminacyjny)
Kolejna kontrolka to TextView z ustawieniami jak poniżej
Następna kontrolka to ImageView z osadzonym obrazem dołączonym do arkusza egzaminacyjnego. Pobierz ten obrazek (pobierz i osadź w projekcie w lokalizacji app/res/drawable.
Kliknij prawym przyciskiem myszki katalogu o nazwie drawable i i wklej skopiowany plik obrazu JPG
Osadź kontrolkę Widgets/ ImageView wraz z obrazem
Osadź kontrolkę układu poziomego, czyli wybierz Layouts/ LinearLayout (horizontal). Osadzona kontrolka rozleje się na cały dostępny obszar. Na tę chwile zignoruj to. Osadź trzy przyciski (kontrolka Button). Przejdź do właściwości kontrolki LinearLayout (horizontal) i wybierz layout_height na wrap_content
Ten wybór spowoduje dostosowanie się wysokości kontrolki LinearLayout (horizontal) do osadzonej w niej zawartości przycisków.
Nadaj kolor podany w arkuszu egzaminacyjnym. Odszukaj w atrybutach właściwość background i przypisz wartość #008080
W przypadku kontrolek Button zmiana koloru we właściwości background nic nie da. Najprostszym rozwiązaniem niewymagającym tworzenia nowego wyglądu aplikacji (Theme) jest podmiana w backgroundTinn. Dla przycisków odszukaj w atrybutach właściwość backgroundTinn i ustaw na wskazany kolor #008080
Dodajemy kolejną kontrolkę TextView przeznaczoną na licznik polubień. Ustawiamy w niej textAlignment na textEnd (wyrównanie do prawej) oraz textSize na 20sp. Patrz poniższa ilustracja
Dodajemy poziomą linie podziału Widgets/ Horizonatal Divider. Ustawiamy kolor we właściwości backgroundTint na #808080.
Kolejny komponent to TextView z pogrubiona czcionką o większym rozmiarze, ale mniejszym niż w pierwsza kontrolka TextView. Ustaw jak poniżej
Dodajemy ostatni komponent przeznaczony na tekst opisu atrakcji turystycznej. Parametry dodanej kontrolki TextView ustawiamy tak, aby kontrolka zajęła cały dostępny obszar. Czyli layout_width i layout_height ustawiamy na match_parent.
Wprowadzamy wymagane teksty podane w arkuszu egzaminacyjnym. Widok głównej aktywności jest gotowy. Uruchom aplikację i sprawdź efekt.
Funkcja licznika polubień
Funkcję zliczającą polubienia (w tym usuwanie) napiszemy jako jednoargumentową zwracającą typ Int. Funkcję napiszemy tak, aby można ją było uruchomić pod klawiszem POLUB jak i USUŃ. W ciele funkcji napiszemy warunek zabezpieczający aby licznik nie osiągnął wartości mniejszej niż zero.
Wskazówka:
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
var ile=0;
fun licznikPolubien(dodajodejmij: Int): Int{
//funkcja zwraca sume o jeden więsza lub
//o jeden mniejszą wzalezności czy argument
// jest dodatni (+1) czy ujemny (-1)
ile=ile + dodajodejmij
if(ile<0)ile=0
return ile
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
Dla polubień argumentem będzie 1 (plus jeden), a dla usunięcia polubienia argumentem będzie -1 (minus jeden). Czyli odpowiednie wywołania będą jak poniżej
Wskazówka:
ile=licznikPolubien(1)
ile=licznikPolubien(-1)
Dodajemy tak zwanych słuchaczy zdarzenia kliknięcia w przycisk
W kodzie programu pliku MainActivity.kt dodajemy dwie biblioteki, które umożliwiają parcę z kontrolką Button oraz TextView. UWAGA. Jeżeli tych bibliotek nie dodasz, to w dalszej pracy kompilator sam podpowie o konieczności dodatnia tych bibliotek.
Wskazówka:
import android.widget.Button
import android.widget.TextView
Wskazówka:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//klawisz POLUB
val button1 = findViewById<Button>(R.id.button1)
button1.setOnClickListener {
//zwiększ licznik o jeden
ile=licznikPolubien(1)
//uaktualnij komunikat
val txt=findViewById<TextView>(R.id.textView2)
txt.text= ile.toString()+" polubień"
}
}
Skompiluj program i sprawdź efekt działania. Aplikacja zachowuje się jak poniżej.
Analogicznie dodajemy obsługę klawisza USUŃ polubienie. Jedyna różnica to ujemny argument podany do funkcji licznikPolubien()
Wskazówka:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//klawisz POLUB
val button1 = findViewById<Button>(R.id.button1)
button1.setOnClickListener {
//zwieksz licznik o jeden
ile=licznikPolubien(1)
//uaktualnij komunikat
val txt=findViewById<TextView>(R.id.textView2)
txt.text= ile.toString()+" polubień"
}
//klawisz USUŃ
val button2 = findViewById<Button>(R.id.button2)
button2.setOnClickListener {
//zmniejsz licznik o jeden
ile=licznikPolubien(-1)
//uaktualnij komunikat
val txt=findViewById<TextView>(R.id.textView2)
txt.text= ile.toString()+" polubień"
}
}
Skompiluj program i sprawdź zachowanie się aplikacji. Aplikacja powinna zwiększać jak i zmniejszać licznik polubień z równoczesnym zabezpieczeniem przed przekroczeniem wartości poniżej zera.
Pełny kod aplikacji
Zawartość pliku MainActivity.kt
Wskazówka:
package pl.afizyka.ofertyturystyczne
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
class MainActivity : AppCompatActivity() {
var ile=0;
fun licznikPolubien(dodajodejmij: Int): Int{
//funkcja zwraca sume o jeden więsza lub
//o jeden mniejszą w zależności czy argument
// jest dodatni (+1) czy ujemny (-1)
ile=ile + dodajodejmij
if(ile<0)ile=0
return ile
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//klawisz POLUB
val button1 = findViewById<Button>(R.id.button1)
button1.setOnClickListener {
//zwieksz licznik o jeden
ile=licznikPolubien(1)
//uaktualnij komunikat
val txt=findViewById<TextView>(R.id.textView2)
txt.text= ile.toString()+" polubień"
}
//klawisz USUŃ
val button2 = findViewById<Button>(R.id.button2)
button2.setOnClickListener {
//zmniejsz licznik o jeden
ile=licznikPolubien(-1)
//uaktualnij komunikat
val txt=findViewById<TextView>(R.id.textView2)
txt.text= ile.toString()+" polubień"
}
}
}
Zawartość pliku XML zasobu układu widoku głównej aktywności (plik activity_main.xml)
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="20dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Domek w górach"
android:textSize="48sp" />
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:srcCompat="@drawable/obraz" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#008080"
android:orientation="horizontal">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:backgroundTint="#008080"
android:text="POLUB" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:backgroundTint="#008080"
android:text="USUŃ" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:backgroundTint="#008080"
android:text="ZAPISZ" />
</LinearLayout>
<TextView
android:id="@+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="0 polubień"
android:textAlignment="textEnd"
android:textSize="20sp" />
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?android:attr/listDivider"
android:backgroundTint="#808080" />
<TextView
android:id="@+id/textView3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Opis"
android:textSize="24sp"
android:textStyle="bold" />
<TextView
android:id="@+id/textView4"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Odwiedź komfortowy domek w Sudetach, blisko do szlaków turystycznych"
android:textSize="20sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>