忘れん坊のサンタクロース

iOS,Androidアプリ開発についての忘備録です。技術関連情報など掲載していこうかと考えています。時々関係ないことも書くかも。。

Fragmentでのイベントハンドリング

FragmentにButtonを置いてみたけどレイアウトで定義したButtonのonClickがFragmentで実装できないじゃん!!とかいろいろな問題に直面したので頭を冷やして解決方法をメモします。

まず上記の例に関して言えば、そのFragmentを持つActivityで実装することができます。しかし、Fragmentが複数ある場合、FragmentそれぞれのボタンのイベントをActivityで実装しなければならず、Activityが煩雑化してしまいます。FragmentのイベントはFragmentで完結させたいですよね。と言うことで解決方法について説明します。

IDでボタンのインスタンスを取得して、リスナーを登録する

これは超簡単!
まずレイアウトで定義したウィジェットのIDからオブジェクトを取得します。
その後、リスナーを登録してあげれば完成です。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    View view = (View)inflater.inflate(R.layout.fragment_main, container, false);

    //IDからオブジェクトを取得
    Button button  = (Button)view.findViewById(R.id.button);

    //リスナーを登録
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.v("button:", "clicked!");
        }
    });

    return view;
}

これでButtonをタップするとログにメッセージが表示されると思います。

アクティビティへのイベントコールバックを作成する

こちらは公式サイトのAPIガイドにある方法なのですが、Activityの何かしらの情報の取得やUIの操作をするのであれば以下のように実装しましょう。

まずはFragmentにInterfaceを定義しましょう。

public class MainFragment extends Fragment {

 //Activityにイベントを通知する役割を持つ
    public interface OnClickListener {
        void onClick();
    }
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        return inflater.inflate(R.layout.fragment_main, container, false);
    }
}

このOnClickListenerをActivityのインターフェースにしてonClickを実装します。

public class MainActivity extends AppCompatActivity implements MainFragment.OnClickListener {

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

    @Override
    public void onClick() {
        Log.v("onClick:", "想いよ届け");
    }
}

その後、Fragmentに戻ってOnClickListenerの変数をフィールド持ち、Fragmentのライフサイクルの一つであるonAttach()を以下のように実装します。

public class MainFragment extends Fragment {

    OnClickListener _clickListener;

    public interface OnClickListener {
        void onClick();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        return inflater.inflate(R.layout.fragment_main, container, false);
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            _clickListener = (OnClickListener) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(getActivity().toString() + "must implement OnArticleSelectedListener.");
        }
    }
}

ちなみにonAttach()はFragmentをActivityに追加する際に呼ばれるメソッドです。メモメモ、、。
onAttach()内ではActivityがOnClickListenerを実装しているかをハンドリングし、成功すればそれをフィールドに持つようにしています。これで先ほどのIDでオブジェクトを取得する方法と合わせて、

    //リスナーを登録
 button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
                _clickListener.onClick();
        }
    });

これでFragmentのButtonを押した際のイベントがActivityに通知されるようになります。
この方法、Buttonに限らずListViewのタッチイベント(むしろこっちの方が多いかも)などでも使用する場面があると思うのでいろいろと応用がきくと思います。

Fragmentを表示する方法

Fragmentを利用する場合API level > 11が必要

手順

  • fragmentのレイアウト作成
  • Fragmentのサブクラス作成
  • Activityのレイアウトにて紐付け

詳細

fragmentのレイアウト作成します。res->layoutでレイアウト(ここではfargment_main.xml)を作成して以下を記述。

<?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:text="fragment"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"/>

</RelativeLayout>

続いてFragmentのサブクラス(ここではMainFragment)を作成して以下を記述しましょう。

public class MainFragment extends Fragment {

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

最後にActivityに紐付いているxml(ここではactivity_main.xml)で以下を記述して完成です。

<fragment
    android:name="com.sfs.crypton.myapplication.MainFragment"
    android:id="@+id/mainFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

Androidでシンプルなリストを表示する

まずは表示するActivityのxmlにListViewを定義しましょう。
res->layoutにあるxmlファイルにて以下を記述します。

   <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

続いてそのActivityのクラス内のonCreateメソッドにて以下のように記述します。

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

        //xmlで定義したListViewを紐付ける
        ListView listView = (ListView)findViewById(R.id.listView);

        //adapterを生成して、ListViewにセットする
        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
        arrayAdapter.add("list1");
        arrayAdapter.add("list2");
        arrayAdapter.add("list3");
        
        if(listView != null) listView.setAdapter(arrayAdapter);
    }

以上でひとまずは、リストが表示されるかと思います。


f:id:appera:20160905125132p:plain


ここからカスタムレイアウトを作成したり、いろいろな応用すると勉強になるかと思います。
Adapterについてじっくり学習することがミソです。

アプリ開発にあたっての学習資料

 
学習後に得られる技術、知識

 
Apple Developer日本語ドキュメント一覧
 
 
iOS アプリケーションプログラミングガイド
(※資料抜粋:この資料は、iOSアプリケーション開発の初心者向けではありません。App Storeでの配布に向けて、 アプリケーションの仕上げ段階に到った開発者が対象です。アプリケーションがシステムとどのよう にやり取りするか、円滑にやり取りできるようにするにはどうすればよいか、を検討するためのガイ ドとして利用してください。)
 
Objective-C プログラミングの概念
 
iOSテクノロジーの概要
(※主にフレームワークに関する内容、じっくり読む必要はないが一通り目を通しておくと役立つ)
 
Swift Programming Series(iBook
  • The Swift Programing Language(Swift 2.2)
  • The Swift Programing Language(Swift 3 Beta)
  • Using Swift with Cocoa and Objective-C(Swift 2.2)
  • Using Swift with Cocoa and Objective-C(Swift 3 Beta)
 
The Swift Programing Language日本語訳(Swiftのバージョン不明)
 
 

 
Android Developers APIガイド
 
UDACITY
 
 
プログラミング設計、概念

 
プログラマーの常識をJavaで身につける
 
プログラミング講座
 
オブジェクト指向でなぜつくるのか-第2版-平澤-章
入門-オブジェクト指向設計―変更に強く生産性が高いシステムを-滝沢-克泰

Androidのコンポーネントについて

アクティビティ
アクティビティは1つのUIで1つの画面を表す。

サービス
長時間の操作やリモートプロセスを処理するためのバックグラウンドで実行するコンポーネント

コンテンツプロバイ
共有されているアプリデータの管理。データはファイルシステム、システム、SQLiteデータベース、ウェブ、アプリがアクセスできるあらゆる永続性のストレージに保存できる。
コンテンツプロバイダを介して、他のアプリがデータをクエリしたり、修正したりすることもできる。

ブロードキャストレシーバー
ブロードキャストレシーバーは共有されているアプリデータを管理する。データは、ファイル、システム、SQLiteデータベース、ウェブ、アプリがアクセスできる、あらゆる永続性のストレージに保存できる。コンテンツプロバイダを介して、他のアプリがデータをクエリしたり、修正することもできる。例えばAndroidシステムではユーザーの連絡先情報を管理するコンテンツプロバイダーの一部(ContactsContract.Dataなど)に問い合わせて、特定の人物に関する情報を読み取ったり書き込んだりできる。