Как создать собственную библиотеку для Android на примере BottomTabLayout

Как создать собственную библиотеку для Android на примере BottomTabLayout

Рано или поздно у всех разработчиков накапливается достаточное количество готовых решений и хочется поделиться ими с друзьями, сотрудниками или со всем миром. Но к сожалению у большинства «руки не доходят», так как нужно оформить решение как отдельную библиотеку и потом разобраться как залить ее на открытый репозиторий. К тому же бытует мнение что это не так просто. Так вот, в этой статье мы разрушим этот миф, так как с приходом Gradle в стек технологий Android все стало намного проще.

Использование BottomTabLayout

Понятно, что первый шаг — написание собственной библиотеки. В этом примере я использую библиотеку BottomTabLayout. Эта библиотека позволяет в несколько строчек добавить нижний TabLayout, который перекочевал к нам в Android из мира iOS.

Библиотека BottomTabLayout в действии

1. Набор табов задается через xml-файл ресурсов menu. Например:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="https://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/menu_button1"
        android:icon="@drawable/tab_button1_selector"
        android:title="Button1" />
 
    <item
        android:id="@+id/menu_button2"
        android:icon="@drawable/tab_button1_selector"
        android:title="Button2" />
 
    <item
        android:id="@+id/menu_button3"
        android:icon="@drawable/tab_button1_selector"
        android:title="Button3" />
</menu>

2. В коде выше свойство icon — это ресурс selector, который мы создаем в drawable:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="https://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_button1_dark" android:state_pressed="true" /> <!-- pressed -->
    <item android:drawable="@drawable/ic_button1_dark" android:state_selected="true" /> <!-- selected -->
    <item android:drawable="@drawable/ic_button1" /> <!-- default -->
</selector>

Состояния state_selected и default здесь обязательные, так как нам нужно выделять выбранный таб.

3. Создаем selector для текста:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="https://schemas.android.com/apk/res/android">
    <item android:color="@color/black" android:state_pressed="true" /> <!-- pressed -->
    <item android:color="@color/black" android:state_selected="true" /> <!-- selected -->
    <item android:color="@color/white" /> <!-- default -->
</selector>

4. Создаем стиль текста:

<style name="TabButtonTextStyle" parent="android:Widget.Button">
        <item name="android:textSize">12sp</item>
        <item name="android:textColor">@drawable/tab_button_text_selector</item>
</style>

5. Добавляем BottomTabLayout на разметку activity:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.stfalcon.bottomtablayout_sample.MainActivity">
 
    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/bottomTabLayout" />
 
    <com.stfalcon.bottomtablayout.BottomTabLayout
        android:id="@+id/bottomTabLayout"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:layout_alignParentBottom="true"
        android:background="@color/dark" />
</RelativeLayout>

6. Настраиваем в классе activity:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        container = R.id.container; //Container for fragments
        //Setup button tab layout
        bottomTabLayout = (BottomTabLayout) findViewById(R.id.bottomTabLayout);
        //set button text style
        bottomTabLayout.setButtonTextStyle(R.style.TextGray16);
        // set buttons from menu resource
        bottomTabLayout.setItems(R.menu.menu_bottom_layout);
        //set on selected tab listener.
        bottomTabLayout.setListener(new BottomTabLayout.OnItemSelectedListener() {
            @Override
            public void onItemSelected(int id) {
                switchFragment(id);
            }
        });
        //set button that will be select on start activity
        bottomTabLayout.setSelectedTab(R.id.menu_button1);
    }

7. В нашем примере при переключении таба меняется фрагмент в контейнере:

**
     * Show fragment in container
     * @param id Menu item res id
     */
    public void switchFragment(int id) {
        Fragment fragment = null;
        switch (id) {
            case R.id.menu_button1:
                fragment = ColoredFragment.newInstance(R.color.blue, "Fragment 1");
                break;
            case R.id.menu_button2:
                fragment = ColoredFragment.newInstance(R.color.green, "Fragment 2");
                break;
            case R.id.menu_button3:
                fragment = ColoredFragment.newInstance(R.color.pink, "Fragment 3");
                break;
            case R.id.menu_button4:
                fragment = ColoredFragment.newInstance(R.color.blueDark, "Fragment 4");
                break;
            case R.id.menu_button5:
                fragment = ColoredFragment.newInstance(R.color.white, "Fragment 5");
                break;
        }
        if (fragment != null) {
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            transaction.replace(container, fragment);
            transaction.commit();
        }
    }

Вот такая вот простенькая библиотека. На GitHub можно подробней ознакомится с BottomTabLayout.

Публикация Android-библиотеки

Теперь я расскажу вам, как имея похожие наработки, поделиться ими с миром.

Создание модуля в Android Studio

1. Для начала создаем проект в Android Studio. Для удобства модуль app переименовываем в sample. Здесь будет лежать пример использования нашей библиотеки.

2. Создаем новый модуль:

Создание нового модуля в Android Studio

3. Тип модуля выбираем Android Library:

Выбор типа модуля в Android Studio

4. Это и будет наша библиотека, поэтому название соответствующее — bottomtablayout.

5. Теперь settings.gradle у нас должен выглядеть так:

include ':sample', ':bottomtablayout'

6. В модуле sample, в build.gradle добавляем зависимость:

compile project(':bottomtablayout')

Это делается временно, пока наша библиотека существует только локально.

7. Теперь мы можем написать нашу библиотеку (или перенести готовый код) и протестировать ее в модуле sample.

8. Когда библиотека готова, заливаем ее на свой GitHub-аккаунт.

9. Пишем туториал в README.md.

Добавление библиотеки на Bintray

1. Если библиотека готова и вы считаете что пора миру ее увидеть, заходим и регистрируемся на сайте Bintray.

2. В файл build.gradle проекта добавляем зависимость:

dependencies {
   ...
   classpath 'com.novoda:bintray-release:0.3.4'
}

3. В build.gradle-файле модуля библиотеки (в нашем случае это bottomtablayout) применяем плагин:

apply plugin: 'com.novoda.bintray-release'

И в этом же файле:

publish {
   groupId = 'com.github.stfalcon'
   artifactId = 'contentmanager'
   publishVersion = '0.1.1'
   desc = 'Library that helps a few lines of code to get pictures and video from the android file system, or ures cloud, as well as the camera device.'
   licences = ['Apache-2.0']
   uploadName='ContentManager'
   website = 'https://github.com/stfalcon-studio/ContentManager.git'
}

Где:

  • groupId — пакет (может отличаться от пекейджа самого модуля). Рекомендую называть groupId так: com.github.<username вашего github аккаунта>, поскольку если вы когда-то захотите залить свою библиотеку на Maven Central нужно быть владельцем домена который фигурирует в названии groupId.
  • artifactId — название модуля.
  • publishVersion — версия публикации.
  • desc — описание библиотеки.
  • licences — лицензия.
  • uploadName — название библиотеки.
  • website — ссылка на GitHub проекта.

4. Далее нам нужен API Key вашего аккаунта на Bintray. Заходим на страницу вашего профайла:

Профиль на Bintray

5. Ищем кнопочку Edit и переходим по ней:

Редактирование профиля Bintray

6. Теперь переходим по пункту меню API Key:

Получение API Key с Bintray

7. Сохраняем ключ в надежном месте.

8. Открываем терминал в Android Studio и выполняем:

gradlew clean build bintrayUpload -PbintrayUser=<юзернейм на bintray> -PbintrayKey=<api ключ с bintray> -PdryRun=false

9. Дожидаемся сборки и отгрузки библиотеки на сервер.

10. Теперь открываем сайт Bintray и ищем переход на страницу свежедобавленной библиотеки.

11. Пока что для того, чтобы подключить нашу библиотеку нужно добавить ссылку на репозиторий в build.gradle-файл проекта:

repositories {
    maven {
        url  "https://dl.bintray.com/<username>/maven" 
    }
}

Какой-то лишний шаг получается, правда? Значить нужно это исправить :)

Добавление Android-библиотеки в jCenter

С недавних пор, репозиторием по умолчанию в Android считается jCenter (до этого был Maven Central). Благо, что добавление библиотеки в jCenter делается в один клик.

1. На странице нашей библиотеки переходим по ссылке add to jCenter и отправляем запрос на добавление. В течении суток библиотека будет добавлена в jCenter и вас оповестят соответствующим письмом на почту.

2. Теперь есть возможность подключить библиотеку через build.gradle модуля, добавив зависимость в dependencies:

compile 'com.github.stfalcon:contentmanager:0.1.1'

Завершение

Поздравляю! Ваша библиотека вышла в свет и уже можно начинать хвастаться ею перед друзьями, пиарить в пабликах и смотреть, как страница библиотеки на гитхабе набирает звездочки и форки.

UPD: читайте о наших Android-библиотеках в новой статье!

Нужен MVP, разработка под iOS, Android или прототип приложения? Ознакомьтесь с нашим портфолио и сделайте заказ уже сегодня!