Android Sliding Tabs – раздвижные вкладки в стиле Material Design

Как вы могли заметить, Google обновил многие из своих приложений в стиле Material Design. Одним из основных визуальных изменений в обновления является обновленные раздвижные вкладки. Google дает хорошие руководящие принципы по разработке приложений с вкладками (узнать больше), но не спешит обновлять документацию. В этом учебном пособии я покажу вам, как создать Android приложение с табами – раздвижными вкладками в материальном стиле.

Приступая к работе

1. Добавьте библиотеки appcompat-v7.21.0.+ и appcompat-v4.21.0.+ в файл сборки build.gradle вашего проекта:

[pastacode lang=”java” message=” build.gradle” highlight=”” provider=”manual”]

apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.1"

    defaultConfig {
        applicationId "samples.exoguru.materialtabs"
        minSdkVersion 16
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.3'
    compile 'com.android.support:support-v4:21.0.3'
} 

[/pastacode]

2. Так как Google не обновил их документацию, нам придется украсть два java-файла из открытого исходного кода приложения Google I/O  и вставим его в наш пакет java, чтобы наши вкладки выглядели так же, как в обновленных приложениях Google apps. Вы можете получить эти файлы с ссылке ниже:

SlidingTabLayout.java
SlidingTabStrip.java

3. Создайте новый файл с именем colors.xml в папке ресурсов и добавьте следующий код:

[pastacode lang=”bash” message=”colors.xml” highlight=”” provider=”manual”]



    #00897B
    #00695C
    #004D40

[/pastacode]

4. Создайте новый файл в вашей папке res/color/ и присвойте ему имя selector.xml. После этого добавьте следующий код в него. Этот XML-код изменяет цвет текста активной вкладки, позже мы увидим связанный код стороне Java.

[pastacode lang=”java” message=”selector.xml” highlight=”” provider=”manual”]



     
     
     
     

[/pastacode]

Файлы макетов

5. Вставьте следующий код в файл styles.xml:

[pastacode lang=”php” message=”styles.xml” highlight=”” provider=”manual”]

 



 

[/pastacode]

6. Создайте новый файл с именем tool_bar.xml в папке макетов и вставьте следующий код в него:

[pastacode lang=”php” message=”tool_bar.xml ” highlight=”” provider=”manual”]

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:background="@color/ColorPrimary"
    android:elevation="2dp"
    android:theme="@style/Base.ThemeOverlay.AppCompat.Dark"
    xmlns:android="http://schemas.android.com/apk/res/android" />

[/pastacode]

7. Теперь нам нужно добавить Toolbar, SlidingTabLayout и ViewPager в наше Main Activity, поэтому добавьте следующий код в ваш файл activity_main.xml в папке макетов:

[pastacode lang=”php” message=”activity_main.xml” highlight=”” provider=”manual”]

<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"
    tools:context=".MainActivity">

    <include
        android:id="@+id/tool_bar"
        layout="@layout/tool_bar"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        />

    <samples.exoguru.materialtabs.SlidingTabLayout
        android:id="@+id/tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:elevation="2dp"
        android:background="@color/ColorPrimary"/>

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:layout_weight="1">
     </android.support.v4.view.ViewPager>

</LinearLayout>

[/pastacode]

8. Создадим файлы макетов для вкладок. В моем случае я использую 2 вкладки, и я их называл, tab_1.xml и tab_2.xml:

[pastacode lang=”php” message=”tab_1.xml” highlight=”” provider=”manual”]

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

   
     <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="Tab 1 says Hello :D"
        android:id="@+id/textView"
        android:textColor="@color/tabsScrollColor"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />

</RelativeLayout>

[/pastacode]

[pastacode lang=”php” message=”tab_2.xml” highlight=”” provider=”manual”]

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

   
     <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="Tab 2 says Hello :D"
        android:id="@+id/textView"
        android:textColor="@color/tabsScrollColor"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />

</RelativeLayout>

[/pastacode]

Java-файлы

9. Теперь нам нужно сделать два фрагмента для вкладок и макетов, которые мы создали раньше. Нужно создать два java-файла в каталоге Java и добавить следующий код в них, в моем случае я назвал файлы Tab1.java и Tab2.java:

[pastacode lang=”java” message=”Tab1.java” highlight=”” provider=”manual”]

package samples.exoguru.materialtabs;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by Edwin on 15/02/2015.
 */
public class Tab1 extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v =inflater.inflate(R.layout.tab_1,container,false);
        return v;
    }
}

[/pastacode]

[pastacode lang=”java” message=”Tab2.java” highlight=”” provider=”manual”]

package samples.exoguru.materialtabs;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by Edwin on 15/02/2015.
 */
public class Tab2 extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v =inflater.inflate(R.layout.tab_2,container,false);
        return v;
    }
}

[/pastacode]

10. Для обеспечения представления для каждой вкладки, нам нужен ViewPagerAdpater. Создаем новый файл java с именем ViewPagerAdpater.java и добавим в него следующий код:

[pastacode lang=”java” message=”ViewPagerAdpater.java ” highlight=”” provider=”manual”]

package samples.exoguru.materialtabs;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;

/**
 * Created by Edwin on 15/02/2015.
 */
public class ViewPagerAdapter extends FragmentStatePagerAdapter {

    CharSequence Titles[]; // This will Store the Titles of the Tabs which are Going to be passed when ViewPagerAdapter is created
    int NumbOfTabs; // Store the number of tabs, this will also be passed when the ViewPagerAdapter is created


    // Build a Constructor and assign the passed Values to appropriate values in the class
    public ViewPagerAdapter(FragmentManager fm,CharSequence mTitles[], int mNumbOfTabsumb) {
        super(fm);

        this.Titles = mTitles;
        this.NumbOfTabs = mNumbOfTabsumb;

    }

    //This method return the fragment for the every position in the View Pager
    @Override
    public Fragment getItem(int position) {

        if(position == 0) // if the position is 0 we are returning the First tab
        {
            Tab1 tab1 = new Tab1();
            return tab1;
        }
        else             // As we are having 2 tabs if the position is now 0 it must be 1 so we are returning second tab
        {
            Tab2 tab2 = new Tab2();
            return tab2;
        }

    }

    // This method return the titles for the Tabs in the Tab Strip

    @Override
    public CharSequence getPageTitle(int position) {
        return Titles[position];
    }

    // This method return the Number of tabs for the tabs Strip

    @Override
    public int getCount() {
        return NumbOfTabs;
    }
}

[/pastacode]

11. Теперь вам нужно обновить класс populateTabStrip() в файле SlidingTabLayout.Java, просто замените его следующим кодом:

[pastacode lang=”java” message=”SlidingTabLayout.Java” highlight=”” provider=”manual”]

private void populateTabStrip() {
        final PagerAdapter adapter = mViewPager.getAdapter();
        final View.OnClickListener tabClickListener = new TabClickListener();

        for (int i = 0; i < adapter.getCount(); i++) {
            View tabView = null;
            TextView tabTitleView = null;

            if (mTabViewLayoutId != 0) {
                // If there is a custom tab view layout id set, try and inflate it
                tabView = LayoutInflater.from(getContext()).inflate(mTabViewLayoutId, mTabStrip,
                        false);
                tabTitleView = (TextView) tabView.findViewById(mTabViewTextViewId);
            }

            if (tabView == null) {
                tabView = createDefaultTabView(getContext());
            }

            if (tabTitleView == null && TextView.class.isInstance(tabView)) {
                tabTitleView = (TextView) tabView;
            }

            if (mDistributeEvenly) {
                LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) tabView.getLayoutParams();
                lp.width = 0;
                lp.weight = 1;
            }

            tabTitleView.setText(adapter.getPageTitle(i));
            tabView.setOnClickListener(tabClickListener);
            String desc = mContentDescriptions.get(i, null);
            if (desc != null) {
                tabView.setContentDescription(desc);
            }

            mTabStrip.addView(tabView);
            if (i == mViewPager.getCurrentItem()) {
                tabView.setSelected(true);
            }

            tabTitleView.setTextColor(getResources().getColorStateList(R.color.selector));
            tabTitleView.setTextSize(14);
        }
    }

[/pastacode]

12. И наконец, обновим класс MainActivity.java путем добавления кода ниже:

[pastacode lang=”java” message=”MainActivity.java” highlight=”” provider=”manual”]

package samples.exoguru.materialtabs;

import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;

/**
 * Created by Edwin on 15/02/2015.
 */
public class MainActivity extends ActionBarActivity {

    // Declaring Your View and Variables

    Toolbar toolbar;
    ViewPager pager;
    ViewPagerAdapter adapter;
    SlidingTabLayout tabs;
    CharSequence Titles[]={"Home","Events"};
    int Numboftabs =2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        // Creating The Toolbar and setting it as the Toolbar for the activity

        toolbar = (Toolbar) findViewById(R.id.tool_bar);
        setSupportActionBar(toolbar);


        // Creating The ViewPagerAdapter and Passing Fragment Manager, Titles fot the Tabs and Number Of Tabs.
        adapter =  new ViewPagerAdapter(getSupportFragmentManager(),Titles,Numboftabs);

        // Assigning ViewPager View and setting the adapter
        pager = (ViewPager) findViewById(R.id.pager);
        pager.setAdapter(adapter);

        // Assiging the Sliding Tab Layout View
        tabs = (SlidingTabLayout) findViewById(R.id.tabs);
        tabs.setDistributeEvenly(true); // To make the Tabs Fixed set this true, This makes the tabs Space Evenly in Available width

        // Setting Custom Color for the Scroll bar indicator of the Tab View
        tabs.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
            @Override
            public int getIndicatorColor(int position) {
                return getResources().getColor(R.color.tabsScrollColor);
            }
        });

        // Setting the ViewPager For the SlidingTabsLayout
        tabs.setViewPager(pager);



    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

[/pastacode]

Теперь можно запустить приложение и вы должны получить работающие вкладки в стиле Material Design.

Более наглядно весь процесс смотрите в видео:

Ссылка на исходный код проекта.

Перевод источника.

Продвинутый пример создания вкладок в курсе уроков по созданию реального приложения.

 

Коментарі: 5
  1. Марат Ниматуллов

    А так же не понятно. Я нашел эти два файла.
    SlidingTabLayout.java
    SlidingTabStrip.java
    Что я должен с ними сделать?

  2. Марат Ниматуллов

    Не могу скачать исходный код проекта. Помогите.

  3. detsat

    В десятом пункте ошибка “ViewPagerAdpater”

  4. Anton

    Подскажите, как можно разместить на вкладке иконку вместо текста, заранее спасибо

Додати коментар

Цей сайт використовує Akismet для зменшення спаму. Дізнайтеся, як обробляються дані ваших коментарів.