SWZWの雑記帳

SWZWがいろいろやってる趣味等に関することを適当にかきます

Android用Twitter自作クライアントをつくろうとした話 ~レイアウトについて~

この記事はKobe University Advent Calendar 2016の12日目の記事です.

AndroidはひよっこですがTwitterアプリ作りかけたのでそのメモ書き程度に記事にしました. いろいろ間違ってるかもしれないけど気にしない.

きっかけ

最近Twitterの公式アプリが広告やおすすめなどが段々増えて正直邪魔になってきました.
あと, 誤いいね(旧誤ふぁぼ)が公式アプリは多発するのも使いづらかったです.
他の非公式のTwitterアプリも何個か使ってみたけど, しっくりきたものがなく, なかったら作ろうということでプログラミングの勉強も兼ねて作ろうということになりました.
(Twitterの存続が危なくなってきた時期に作り始めるのはミスだとかそんなことはないと信じる)

とりあえず

今回の記事はアプリのレイアウトを考えるところだけ書きます.
オリジナルで使いやすいレイアウトを考えるほどデザイン発想力がなかったので今回は公式に近いものを作っていきたいです.

レイアウト

準備

今の公式アプリのデザインはGoogle系統のアプリでもよく見るAndroidDesignSupportLibraryのCoordinatorLayoutっぽいのでそれで作っていきます.
minSdkVersionは14(Android4.0以上)みたいですね.

とりあえず, 使うためにAndroidStudioでProjectStructureのModulesの中のDependenciesに追加. あとでrecyclerviewも使うので

  • com.android.support:design
  • com.android.support:recyclerview-v7

の2つを追加.

構成

メインのレイアウトの構成

<android.support.v4.widget.DrawerLayout>
    <android.support.design.widget.CoordinatorLayout>
        <android.support.design.widget.AppBarLayout>
            <android.support.v7.Toolbar>
                <TextView/>
            </android.support.v7.Toolbar>
            <android.support.design.widget.TabLayout/>
        </android.support.design.widget.AppBarLayout>
        <android.support.v4.view.ViewPager/>
        <android.support.design.widget.FloatingActionButton/>
    </android.support.design.widget.CoordinatorLayout>
</android.support.v4.widget.DrawerLayout>

公式アプリでいうプロフィール等にとぶための左のメニューのために一番親のレイアウトをDrawerLayoutにします.
また, 上にスワイプしたら一部が隠れるようなAppBarLayoutや, 右下のツイートボタンになっているFAB(FloatingActionButton)を利用するために, CoordinatorLayoutをDrawerLayoutの一つ下の階層のレイアウトにします.
あとは, AppBarLayoutの挙動に関わるToolbarとTabLayoutをAppBarLayoutの子に配置して, TLやらが表示されるメイン画面になるViewPagerとツイートボタンになるFABをそれぞれCoordinatorLayoutの子にすればOK.

TLや自分あてツイートの一覧等の中身はそれぞれFragment作って, FragmentPagerAdapterを継承したクラスに登録すればいける.

TL用Fragment

メイン画面になるであろうTLのFragmentだけ構成やらを書きます.(というかTL用の画面しかまだ作ってない)
とりあえず構成とFragmentの中身

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

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipeLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" >

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycleView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </android.support.v4.widget.SwipeRefreshLayout>

</RelativeLayout>

一番親は適当にRelativeLayoutを配置. TLの画面を下にスワイプしたら更新するように, 次の階層にSwipeRefreshLayoutを配置.一番下の階層にはTLのためにTweetのリストを表示するRecyclerViewを配置しておきます.
ListViewではなくRecyclerViewなのはListViewだとどれかがうまくいかなくなったので変えたのですが忘れました.(すみません)
まあカスタマイズいろいろできるしTweetのリストはRecyclerViewでします.

あと, 基本全部idとかlayout関係だけだが, SwipeRefreshLayoutはリストの一番上になった時のみ下にスワイプすることで更新するようにするため, SwipeRefreshLayoutにはlayout_behaviorも追加.

Fragmentの実装はこんな感じで. Twitter系統の情報の取得はtwitter4jを使用しています.

public class MainFragment extends Fragment {

    private RecyclerView mRecyclerView;
    private RecyclerAdapter recyclerAdapter;
    private List<twitter4j.Status> data;
    private Twitter mTwitter;
    private SwipeRefreshLayout mSwipeRefreshLayout;

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

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        data = createData();
        recyclerAdapter = new RecyclerAdapter(getActivity(), data);

        mSwipeRefreshLayout = (SwipeRefreshLayout) getView().findViewById(R.id.swipeLayout);
        mSwipeRefreshLayout.setOnRefreshListener(mOnRefreshListener);

        mRecyclerView = (RecyclerView) getView().findViewById(R.id.recycleView);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
        mRecyclerView.setAdapter(recyclerAdapter);

        mTwitter = TwitterUtils.getTwitterInstance(getActivity());
        reloadTimeLine();


    }


    private List<twitter4j.Status> createData() {
        List<twitter4j.Status> data = new ArrayList<>();
        return data;
    }

    private void reloadTimeLine() {

    (略)

    }


    private SwipeRefreshLayout.OnRefreshListener mOnRefreshListener = new SwipeRefreshLayout.OnRefreshListener(){
        @Override
        public void onRefresh() {
            reloadTimeLine();
            mSwipeRefreshLayout.setRefreshing(false);
        }
    };

}

RecyclerAdapterクラスはRecyclerViewのためのRecyclerView.Adapterを継承した自作クラスです.
リストの要素一つ一つにコンストラクタで取得したタイムラインのリストから名前やら本文やらを登録していってます.

reloadTimeLine()はタイムラインを再取得する関数です.
リストの一番上で下にスワイプすることでmOnRefreshListenerのonRefresh()がよばれてタイムラインを更新してます.

今回は終わり

そもそもまだ自作Twitterクライアント(アプリ)を制作途中なんで, 今回は大まかなレイアウトのまとめということでこの辺で終わります. また進捗があったら自分のメモ書き用程度にまとめるかもしれない.