Szablony w Android Studio

Czy zdarzało Ci się tworzyć ten sam kod kilka razy? A może kopiujesz kod między projektami, klasami i zmieniasz tylko kilka rzeczy, a mimo to tracisz sporo czasu. A może Ty i twój zespół używacie pewnego wzorca w pisaniu kodu? A może dostarczone szablony w Android Studio nie pasuje do tego, czego potrzebujesz?

Mam dla Ciebie świetną informacje!Powiem Ci, że możesz tworzyć własne szablony kodu w IDE i wykorzystywać je wielokrotnie. Brzmi ciekawie? Czytaj dalej.

info:

Poniższe porady również możesz zastosować w programie IntelliJ IDEA. Pamiętaj, że niektóre rzeczy mogą się różnić, na przykład lokalizacja szablonów. W związku z tym musisz dostosować je do własnych potrzeb.

Szablony w Android Studio

Ogólnie rzecz biorąc, w Android Studio już masz zdefiniowane szablony i korzystasz z nich (nie)świadomie.

Szablon to plik źródłowy, który zawiera jakiś kod. Za pomocą takich plików można tworzyć nowe moduły aplikacji, aktywności, fragmenty lub inne specyficzne składniki aplikacji na system Android. Poniżej znajdują się domyslne kategorie szablonów w programie Android Studio.

Podstawowe szablony w Android Studio

Który język jest używany do tworzenia szablonów Android Studio? Jest to silnik szablonów Apache FreeMarker.

Przygotowałem specjalnie dla Ciebie kurs RecyclerView w Androidzie. Wdziałeś go?


Prosty szablon w Android Studio

Poniżej znajduje się przykład prostego szablonu opartego na jednym pliku.

W pierwszej kolejności naciśnij CTRL (CMD) + SHIFT + A, aby znaleźć akcję, wprowadź „Add Template” i naciśnij przycisk Enter. Zostanie otwarte okno ustawień Android Studio z zakładką „File and Code Template„.

Możesz także iść do tego okna poprzez ustawienia (CTRL+ ALT + S) lub naciśnij prawym przyciskiem myszy na folderze „app” w oknie Project (domyślnie po lewej stronie) i wybierając New -> Edit File Templates.

Naciśnij teraz plusik, aby dodać nowy szablon. Nazwij go „RecyclerView Adapter & ViewHolder”, a rozszerzenie daj jako „.kt” (ponieważ korzystamy z języka Kotlin) i dodaj następujący kod:

#if (${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end

class ${NAME} (val context: Context,
               val items : ArrayList<${LIST_MODEL}> )
    : RecyclerView.Adapter<${NAME}.${VIEWHOLDER_CLASS}>() {

    override fun getItemCount() = items.size

    override fun onCreateViewHolder(parent: ViewGroup,viewType: Int): ${VIEWHOLDER_CLASS} {

        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.${LAYOUT_RES_ID}, parent, false)

        return ${VIEWHOLDER_CLASS}(view)
    }

    override fun onBindViewHolder(myHolder: ${VIEWHOLDER_CLASS}, position: Int) {

        myHolder.name.text = items.get(position).name
        myHolder.city.setText(items.get(position).city)
        myHolder.color.setBackgroundColor(Color.parseColor(items.get(position).color))
        myHolder.color.text = position.toString()

    }

    inner class ${VIEWHOLDER_CLASS} (view: View) : RecyclerView.ViewHolder(view) {
        val name = view.name
        val city = view.city
        val color = view.color
    }
}

Naciśnij Apply i Ok. Teraz wywołaj menu kontekstowe na pakiecie, w którym chcesz utworzyć plik.

Dodaj szablon RecyclerView w Android Studio

Przed dodaniem pliku do projektu, pojawi się okno dialogowe, w którym można zdefiniować określone wartości dla wszystkich zmiennych niestandardowych.

Jak widać, piszemy standardowy kod, który jest uzupełniony o dodatkowe zmienne. Wraz ze statycznym kodem i komentarzami można również użyć predefiniowanych zmiennych. Możliwe jest również określenie niestandardowych zmiennych w formacie ${…}.

Predefiniowane zmienne szablonu w Android Studio

Predefiniowane zmienne przyjmą następujące wartości:

  • ${PACKAGE_NAME} – nazwa pakietu, w którym tworzony jest nowy plik.
  • ${NAME} – nazwa nowego pliku określony w oknie dialogowym.
  • ${USER} – bieżąca nazwa użytkownika systemu.
  • ${DATE} – aktualna data systemowa.
  • ${TIME} – aktualny czas systemowy.
  • ${YEAR} – rok bieżący.
  • ${MONTH} – obecny miesiąc.
  • ${MONTH_NAME_SHORT} -pierwsze 3 litery nazwy bieżącego miesiąca.
  • ${MONTH_NAME_FULL} – pełna nazwa bieżącego miesiąca.
  • ${DAY} – bieżący dzień miesiąca.
  • ${DAY_NAME_SHORT} -pierwsze 3 litery nazwy bieżącego dnia.
  • ${DAY_NAME_FULL} – pełna nazwa bieżącego dnia.
  • ${HOUR} – aktualna godzina.
  • ${MINUTE} – aktualna minuta.
  • ${PROJECT_NAME} – nazwa bieżącego projektu.

W naszym szablonie Android Studio dyrektywa if w naszym przypadku służy do sprawdzenia, czy nazwa pakietu nie jest pusta. Używając dyrektywy #parse, możesz dołączyć szablony z karty Includes. Na przykład: #parse („File Header.kt”). Szablony dołączone służą do definiowania fragmentów kodu wielokrotnego użytku. Na przykład standardowych nagłówków, oświadczeń o prawach autorskich itp.

Niestandardowe zmienne szablonu

Oprócz predefiniowanych zmiennych szablonów możliwe jest określenie zmiennych niestandardowych. Jeśli to konieczne, możesz zdefiniować wartości zmiennych bezpośrednio w szablonie za pomocą dyrektywy #set.

#set( $WWW = "myenv.net" )

Gdzie są zapisane szablony?

Szablony możesz znaleźć w lokalizacji:

C:\Users\{USER}\.AndroidStudio{VERSION}\config\fileTemplates\

Rozbudowany przykład

Powyżej został przedstawiony prosty przykład z jednym plikiem. Powyższy sposób działa, ale ma jedną wadę. W naszym przypadku utworzenie samego adaptera nic nie da, ponieważ musimy sami stworzyć model danych, aktywność lub fragment gdzie inicjalizujemy RecyclerView. Do tego dochodzi także pliki z układałem widoków.

Aby utworzyć kompletny szablon, przejdź do folderu:

// Windows 
C:/Program Files/Android/Android Studio/plugins/android/lib/templates/activities/
// Mac
/Applications/Android/Studio.app/Contents/plugins/android/lib/templates/activities/
thumb_up:

W tym folderze znajdziesz szablony, które znajdują się już w Android Studio. Możesz zobaczyć, w jaki sposób są one tworzone. Pomoże Ci to w pisaniu własnych szablonów.

Należy teraz utworzyć nowy katalog — ActivityWithRecyclerView, a następnie utwórz pliki template.xml i recipe.xml.ftl. Stwórz także folder o nazwie root, który będzie przechowywać nasze pliki szablonów.

Istnieje również plik globals.xml.ftl, który zawiera wszystkie zmienne globalne. Dobrą praktyką jest zdefiniowanie zmiennych dla ścieżki katalogu src i res. Jest to plik opcjonalny, dlatego w naszym przykładzie pomijamy go i ścieżki ustawimy na sztywno.

Struktura szablonu będzie przedstawiała sie w następujący sposób:

ActivityWithRecyclerView
    ./template.xml
    ./recipe.xml.ftl
    ./globals.xml.ftl (optional)
    ./ActivityWithRecyclerView.png
    ./root/src/app_package/RecyclerViewActivity.kt.ftl
    ./root/src/app_package/MyRecyclerViewAdapter.kt.ftl
    ./root/src/app_package/Profile.kt.ftl
    ./root/res/layout/activity_recycler_view.xml.ftl
    ./root/res/layout/recyclerview_item.xml.ftl

Plik template.xml

Plik template.xml — definiuje pola wejściowe użytkownika. Są to pola wyboru, listy rozwijane itp., które użytkownik widzi podczas dodawania szablonu do projektu.

Konfiguracja szablonu w Android Studio
<?xml version="1.0"?>
<template 
		format="5"
        revision="1"	
        name="Activity with Recyclerview"
        description="Creates a new activity with Recyclerview">

    <category value="Activity"/>
    <formfactor value="Mobile" />

    <parameter
        id="activityClass"
        name="Activity Name"
        type="string"
        constraints="class|unique|nonempty"
        default="RecyclerViewActivity"
        help="The name of the activity class to create" />

    <parameter
        id="activityLayout"
        name="Layout Name"
        type="string"
        constraints="layout|unique|nonempty"
        default="recyclerview_activity"
        help="The name of the layout to create for the activity" />

 
    <parameter
        id="recyclerViewAdapterClass"
        name="RecyclerView Adapter Name"
        type="string"
        constraints="class|unique|nonempty"
        default="MyRecyclerViewAdapter"
        help="The name of the adapter class" />

    <parameter
        id="recyclerviewItem"
        name="item Layout Name"
        type="string"
        constraints="layout|unique|nonempty"
        default="recyclerview_item"
        help="The name of the item layout" />


    <parameter
        id="packageName"
        name="Package name"
        type="string"
        constraints="package"
        default="net.myenv.recyclerview" />


	<thumbs>
        <!-- Default thumbnail. -->
        <thumb>ActivityWithRecyclerView.png</thumb>
    </thumbs>
	
    <!-- Optional global variables. -->
    <!-- <globals file="globals.xml.ftl" /> -->
    
	<!-- Required recipe (script) to run when instantiating the template. -->
    <execute file="recipe.xml.ftl" />

</template>

W tym pliku definiujemy takie wartości jak:

  • format — wersja formatu szablonu.
  • revision — wersja szablonu. Wraz z aktualizacją szablonu możemy zmieniać tą wartość.
  • name — nazwa szablonu wyświetlanego w Android Studio.
  • description — opis szablonu.
  • minApi / minBuildApi (opcjonalny) — minimalny poziom API wymagany dla tego szablonu.
  • category — do której kategorii szablon należy. Możemy utworzyć też własną kategorię. Na przykład umieść pliki w folderze Custom, a nie w Activity oraz kategorię wpisz jako „Custom”.
  • formfactor — czy chcesz, aby szablon wyświetlał się, gdy tworzysz moduł aplikacji ( Wear, TV itp). Jeśli tak to w jakiej sekcji. Patrz obrazek poniżej.
  • Atrybut parameter zawiera:
    • id — unikalny identyfikator elementu.
    • name — nazwa pola szablonu.
    • type — typ danych elementu.
    • constraints (opcjonalny) — ograniczenia do wpisywanych wartości. Działa jak inputType w edittext.
    • default — wartością domyślną w przypadku, gdy użytkownik pozostawia puste pole.
    • help — informacja dla użytkownika, co dany element reprezentuje.
  • thumb — podgląd szablonu.
  • globals i atrybuty execute łączą nasze pliki globalne i pliki receptur.
Szablony in Android Studio

Plik recipe.xml.ftl

W pliku recipe.xml.ftl  umieszczamy akcję, jakie mają się wykonać. W naszym przypadku pliki z folderu głównego (root) są konwertowane na rzeczywiste pliki Java lub Kotlin. Wskazujemy również jakie pliki powinny zostać otwarte po utworzeniu szablonu w Android Studio.

Możesz również kopiować kod z innych szablonów. Tutaj też defilujesz czy dodać jakieś zależności w pliku gradle. Jeżeli dodajesz aktywność do projektu to musisz także utworzyć odpowiedni wpis w manifeście. Właśnie w tym pliku musisz te informacje zawrzeć.

<?xml version="1.0"?>
<recipe>

    <instantiate from="root/src/app_package/RecyclerViewActivity.kt.ftl"
                   to="${escapeXmlAttribute(srcOut)}/${activityClass}.kt" />

    <instantiate from="root/res/layout/activity_recycler_view.xml.ftl"
                 to="${escapeXmlAttribute(resOut)}/layout/${activityLayout}.xml" />


    <instantiate from="root/src/app_package/MyRecyclerViewAdapter.kt.ftl"
                   to="${escapeXmlAttribute(srcOut)}/${recyclerViewAdapterClass}.kt" />

    <instantiate from="root/res/layout/recyclerview_item.xml.ftl"
                 to="${escapeXmlAttribute(resOut)}/layout/${recyclerviewItem}.xml" />
    
	
	<instantiate from="root/src/app_package/Profile.kt.ftl"
                   to="${escapeXmlAttribute(srcOut)}/Model/Profile.kt" />
    
	
    <open file="${escapeXmlAttribute(resOut)}/layout/${activityLayout}.xml" />
    <open file="${escapeXmlAttribute(srcOut)}/${activityClass}.kt" />
	
    <open file="${escapeXmlAttribute(resOut)}/layout/${recyclerviewItem}.xml" />
    <open file="${escapeXmlAttribute(srcOut)}/${recyclerViewAdapterClass}.kt" />

    <open file="${escapeXmlAttribute(srcOut)}/Model/Profile.kt" />


</recipe>

W przykładzie nie ma zapisu jak dodać aktywność do manifestu. To jest Twoje zadanie 🙂 Jeżeli wiesz jak to zrobić, podziel się tą informacją w komentarzu!

Folder root

W tym folderze będziemy mieć dwa katalogi res i src. W folderze res umieszczamy pliki z zasobami. Natomiast w drugim katalogu będą pliki z kodem źródłowym.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/myRC"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" xmlns:android="http://schemas.android.com/apk/res/android">

    <TextView
            android:layout_width="36dp"
            android:layout_height="34dp"
            android:id="@+id/color"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:layout_marginRight="16dp"
            android:clickable="true"
            android:gravity="center"
            android:text="1"
            android:textSize="25dp"
            android:textStyle="bold"
    />

    <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/name"
            android:layout_toRightOf="@+id/color"
            android:layout_alignParentTop="true"
            android:textSize="30sp"
            android:clickable="true"
    />

    <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/city"
            android:layout_toRightOf="@+id/color"
            android:layout_below="@+id/name"
            android:clickable="true"
    />


    <Button
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:id="@+id/delete"
            android:src="@android:drawable/ic_delete"
            android:layout_alignParentEnd="true"
            android:layout_alignParentBottom="true"
            android:layout_marginStart="16dp"
            android:visibility="invisible"
    />

</RelativeLayout>
package ${packageName}

import android.content.Context
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.${recyclerviewItem}.view.*



class ${recyclerViewAdapterClass} (val context: Context,
									val items : ArrayList<Profile> )
    : RecyclerView.Adapter< ${recyclerViewAdapterClass}.MyViewHolder>() {

    override fun getItemCount() = items.size

    override fun onCreateViewHolder(parent: ViewGroup,viewType: Int): MyViewHolder {

        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.recyclerview_item, parent, false)

        return MyViewHolder(view)

    }

    override fun onBindViewHolder(myHolder: MyViewHolder, position: Int) {

        myHolder.name.text = items.get(position).name
        myHolder.city.setText(items.get(position).city)
        myHolder.color.setBackgroundColor(Color.parseColor(items.get(position).color))
        myHolder.color.text = position.toString()

    }

    inner class MyViewHolder (view: View) : RecyclerView.ViewHolder(view) {
        val name = view.name
        val city = view.city
        val color = view.color
    }

}
package ${packageName}

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.recyclerview.widget.LinearLayoutManager
import io.bloco.faker.Faker
import kotlinx.android.synthetic.main.${activityLayout}.*



class ${activityClass} : AppCompatActivity() {

    private var profiles: ArrayList<Profile> = ArrayList()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.${activityLayout})

        generateProfiles()
    }

    private fun generateProfiles(){
        val thread = object : Thread() {
            override fun run() {

                val faker = Faker()
                for (x in 0 until 20) {
                    profiles.add(Profile(
                                x,
                                faker.name.name(),
                                faker.address.city(),
                                faker.color.hexColor()
                        )
                    )
                }

                runOnUiThread {
                    initRecyclerView()
                }
            }
        }
        thread.start()
    }

    private fun initRecyclerView() {
        myRC.layoutManager = LinearLayoutManager(this)
        myRC.setHasFixedSize(true)

        val adapter = MyRecyclerViewAdapter(this, profiles )
        myRC.adapter = adapter

    }
}
package ${packageName}

data class Profile(var id: Int,
                   var name: String,
                   var city: String,
                   var color: String
)

Testowanie szablonu

Teraz, aby przetestować to, co zostało utworzone, wykonaj następujący kroki:

  1. Otwórz Android Studio lub, jeśli jest otwarte, uruchom go ponownie.
  2. Kliknij prawym przyciskiem myszy na pakiet, w którym chcesz utworzyć szablon i wybierz go z menu: New -> Activity -> ActivityWithRecyclerView.
  3. Wypełnij pola, o które jesteś proszony. 
  4. Poczekaj, aż Android Studio zakończy generowanie plików.
  5. Gotowe!

Uważaj na aktualizacje Android Studio!

Kompletne szablony są świetne do stworzenia większej ilości kodu. Musisz jednak pamiętać, że możesz je stracić podczas aktualizacji Android Studio.

Gdy pojawi sie nowa wersja IDE możesz otrzymać poniższy komunikat.

Program daje warunek. Albo aktualizujesz, albo kasujesz szablony, które utworzyłeś. Przed aktualizacją wykonaj kopie szablonów Android Studio.

Niestety nie znalazłem sposobu, aby kompletne szablony trzymać w folderze z konfiguracją AD. Może masz na to sposób? Daj mi znać w komentarzu 🙂

Live Template

Jeżeli nie wystarczają Ci powyższe szablony, a mimo to chciałbyś jeszcze bardziej przyspieszyć swoją pracę — pisz skrótami. Po co pisać całą strukturę TextView, skoro można napisać tylko tv (lub inny skrót, który wymyślisz sobie).

Naciśnij znany Ci skrót — CTRL (CMD) + SHIFT + A, aby znaleźć akcję, wprowadź “Live Template” i wybierz odpowiednią opcję. Zostanie otwarte okno ustawień Android Studio z zakładką “Live Template“. Dodaj kod, tak jak zostało to przedstawione na poniższym obrazku.

Dodaj live templates w Android Studio

Teraz wystarczy przejść do jakiegoś layoutu i wpisać tv i nacisnąć klawisz TAB. Kod sam się uzupełni. W naszym przypadku stworzyliśmy własną grupę „Custom”, a w niej odpowiedni rekord. Możesz również dodawać wpisy do już istniejących grup.

Szablony możesz znaleźć w lokalizacji:

C:\Users\<strong>{</strong>USER<strong>}</strong>\.AndroidStudio<strong>{</strong>VERSION<strong>}</strong>\config\ftemplates\

Podsumowanie

Używanie szablonów w Android Studio to potężne narzędzie, które przyspieszają proces tworzenia aplikacji na system Android. Szablony te możesz swobodnie przenosić między członkami zespołu, abyście mogli pracować zgodnie ze standardami.

Jeśli spodobał Ci się ten artykuł i uznałeś go za przydatny, nie zapomnij udostępnić go innym użytkownikom. Nie przegap kolejnych nowości na MYENV i bądźmy również w kontakcie. Zapisz się na [sc_signup_newsletter]newsletter[/sc_signup_newsletter], aby mieć jeszcze więcej fajnych materiałów takich jak ten 😉