Android TV 開發 (1)


本文來自網易雲社區html

做者:孫有軍android


前言

這裏主要記錄幾個TV問題的解決方案,若是對這個不感興趣的其實就不用往下看了。算法

這幾天有一個需求就是要求出一個TV版本的app,以前沒有具體的瞭解Tv版的app有手機端的app到底有什麼區別,所以就作了一下研究,寫了些Demo,在作的過程當中確實出現了好幾個問題。一開始碰到這些問題時,淺嘗輒止的試了試,發現不少都沒有解決方案,本着外事問google的,search了一把,也沒有結果,多是TV作的人比較少,網上搜出來的都是照着谷歌官方的樣例實現了一把而已,所以就仔細的研究了一下這些問題,這裏把解決這些問題的方案描述出來,但願其餘人能少走彎路,若是有更好的解決方案也但願你們探討分享。app

開發過程

雖然google官方寫的是手機app不用作太多改動就能夠運行在Tv上,可是終究兩種仍是有部分區別的,這裏仍是要針對TV版作部分設置。
首先是配置文件的改動,須要在AndroidManifest中配置以下屬性:ide

<uses-feature
    android:name="android.hardware.touchscreen"
    android:required="false"/>
<uses-feature
    android:name="android.software.leanback"
    android:required="true"/>

同時還須要配置一個action爲android.intent.action.MAIN,category爲android.intent.category.LEANBACK_LAUNCHER的Activity,相似以下:學習

<activity
    android:name="im.yixin.home.HomeActivity"
    android:label="@string/app_name"
    android:screenOrientation="landscape">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>

        <category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
    </intent-filter>
</activity>

若是記不住上面須要配置的內容其實也沒有關係,能夠新建立一個TV工程,默認建立的TV工程就已經包含了上述的配置,而且該工程就至關於一個demo了,是能夠直接運行的一個工程,裏面包含了Tv開發的不少控件,若是你要學習這也是很好的學習資料了,其實後續的內容也是根據這裏的內容進行參照學習的。ui

這裏附帶一句,Android的sdk中的samples中的tv樣例程序直接導入是運行不起來的,須要修改不少東西,可是實質內容與新建立的工程沒有什麼區別,所以也能夠不用導入樣例程序進行學習了。this

根據前面的樣例圖,主界面配置頁面以下:google

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/global_bg"
    android:orientation="vertical"
    android:paddingLeft="42dp"
    android:paddingRight="42dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/gap_86_dp"
        android:clickable="true">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:drawableLeft="@drawable/tv_logo"
            android:drawablePadding="@dimen/gap_8_dp"
            android:gravity="center"
            android:text="@string/itv_name"
            android:textColor="@color/white"
            android:textSize="@dimen/text_size_20"/>

        <TextView
            android:id="@+id/settings_tab"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_alignParentRight="true"
            android:layout_marginRight="@dimen/gap_45_dp"
            android:background="@drawable/navigation_tab_bar_selector"
            android:focusable="true"
            android:gravity="center"
            android:text="@string/setting"
            android:textColor="@color/navigation_text_selector"
            android:textSize="@dimen/text_size_20"/>

        <TextView
            android:id="@+id/contact_tab"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginRight="@dimen/gap_45_dp"
            android:layout_toLeftOf="@id/settings_tab"
            android:background="@drawable/navigation_tab_bar_selector"
            android:focusable="true"
            android:gravity="center"
            android:text="@string/contact"
            android:textColor="@color/navigation_text_selector"
            android:textSize="@dimen/text_size_20"/>

        <TextView
            android:id="@+id/dial_tab"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginRight="@dimen/gap_65_dp"
            android:layout_toLeftOf="@id/contact_tab"
            android:background="@drawable/navigation_tab_bar_selector"
            android:focusable="true"
            android:gravity="center"
            android:text="@string/dial"
            android:textColor="@color/navigation_text_selector"
            android:textSize="@dimen/text_size_20"/>
    </RelativeLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:layout_marginBottom="@dimen/gap_50_dp"
        android:background="@color/gray1"/>

    <FrameLayout
        android:id="@+id/tab_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></FrameLayout>
</LinearLayout>

界面的代碼以下:xml

public class HomeActivity extends Activity implements View.OnClickListener {

    public static void start(Context context) {
        Intent intent = new Intent(context, HomeActivity.class);
        context.startActivity(intent);
    }

    private static final String[] TAGS = {"dial", "contact", "my"};

    private FragmentManager manager;

    private int showTabIndex = -1;

    private TextView dialTab;
    private TextView contactTab;
    private TextView myTab;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        findViews();
        setViewsListener();
        init();
        selectTab(0);
    }

    private void findViews() {
        dialTab = (TextView) findViewById(R.id.dial_tab);
        contactTab = (TextView) findViewById(R.id.contact_tab);
        myTab = (TextView) findViewById(R.id.settings_tab);
    }

    private void setViewsListener() {
        dialTab.setOnClickListener(this);
        contactTab.setOnClickListener(this);
        myTab.setOnClickListener(this);
    }

    private void init() {
        manager = getFragmentManager();
    }

    private void selectTab(int index) {
        if (index == showTabIndex) {
            return;
        }
        dialTab.setSelected(index == 0);
        contactTab.setSelected(index == 1);
        myTab.setSelected(index == 2);
        FragmentTransaction transaction = manager.beginTransaction();
        hideFragment(showTabIndex, transaction);
        showTabIndex = index;
        showFragment(showTabIndex, transaction);
        transaction.commit();
    }

    private void hideFragment(int tabIndex, FragmentTransaction transaction) {
        Fragment fragment = getFragmentByIndex(tabIndex);
        if (fragment != null) {
            transaction.hide(fragment);
        }
    }

    private Fragment getFragmentByIndex(int index) {
        if (index >= 0 && index < TAGS.length) {
            return manager.findFragmentByTag(TAGS[index]);
        }
        return null;
    }

    private void showFragment(int tabIndex, FragmentTransaction transaction) {
        Fragment fragment = getFragmentByIndex(tabIndex);
        if (fragment == null) {
            switch (tabIndex) {
                case 0:
                    fragment = new DialFragment();
                    break;
                case 1:
                  /*  fragment = new ContactFragment();*/
                    fragment = new VerticalGridFragment();
                    break;
                case 2:
                    fragment = new MyFragment();
                    break;
            }
            transaction.add(R.id.tab_container, fragment, TAGS[tabIndex]);
            //transaction.addToBackStack(TAGS[tabIndex]);
        } else {
            transaction.show(fragment);
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.dial_tab:
                selectTab(0);
                return;
            case R.id.contact_tab:
                selectTab(1);
                return;
            case R.id.settings_tab:
                selectTab(2);
                //                VerticalGridActivity.start(this);
                return;
        }
    }

}

該界面主要採用Fragment來實現三個界面,分別爲撥號頁面,好友,設置界面,其中撥號界面又包含兩個子的Fragment,咱們來繼續看看撥號界面與好友界面,設置界面是一個充數的界面啥都沒有作。


網易雲免費體驗館,0成本體驗20+款雲產品! 

更多網易研發、產品、運營經驗分享請訪問網易雲社區


相關文章:
【推薦】 最小化局部邊際的合併聚類算法(中篇)
【推薦】 淺析Docker容器的應用場景

相關文章
相關標籤/搜索