【Android】Fragment内での子Fragmentを管理する方法
今まではFragmentの管理はActivity単位が基本でしたが、getChildFragmentManager
を使用することでFragment内での子Fragmentを管理することができます。
使用例
Fragment childFragment = new ChildFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.child_fragment, childFragment).commit();
参考サイト:
【Android】画面をスクロールさせる方法
ScrollView
を使用することで、スクロールバーを実現することができます。
スクロールバーの作成
レイアウトファイル(.xml)に以下を追加します。
<ScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:weightSum="1"> <EditText /> <EditText /> <Button /> . . . </LinearLayout> </ScrollView>
ここで注意が必要なのは、ScrollView
のなかに、子要素を一つ入れる必要があるということです。
LinearLayout
がここでいう子要素になります。
子要素がないとScrollView can host only one direct child
というエラーがでるので注意して下さい。
参考サイト:
【Atom】Vimのキーバインドを使用する方法
AtomでVimのキーバインドを使えるプラグインvim-modeというものがあります。
保存(:wq)のキーバインドは使えなかったですが、ほとんどVimのキーバインドは設定することで使用できます。
vim-modeのインストール方法
[Ctrl] + [Shift] + [P]
を入力して、入力欄にsettings ...
と入力します。最初の3文字くらい入力すると補完で
Settings Viewr: Open
とプルダウンに表示されるので、それを選択します。SettingsのInstall Packagesの画面に移動するので、
vim-mode
を検索欄に入力してプラグインをインストールします。インストールが完了したら、画面上のメニューにある
[View]→[Relode]
をクリックして再読み込みをします。最後に、SettingsのPackagesの画面にvim-modeがInstalld Packagesに表示されているので、vim-mode欄の
Settings
をクリックし、vim-modeの詳細画面に移動したあと、Settingsにある4つのチェックボックスにチェックを入れます。
参考サイト:
【Android】FragmentTabHostを使用したタブの作成
FragmentTabHost
はFragmentをタブで切り替えるためのViewです。
タブの作成は以前TabActivityを使っていましたが、現在は非推奨になっているのでFragmentTabHost
の使用をおすすめします。
また、Android 1.6から利用することができるものとなっています。
今回はFragmentにタブを表示する方法と、Fragment内での子Fragmentにタブを表示する方法を書きます。
Fragmentにタブを表示
レイアウトの作成
<android.support.v4.app.FragmentTabHost android:id="@android:id/tabhost" android:layout_width="match_parent" android:layout_height="match_parent"> <RelativeLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TabWidget android:id="@android:id/tabs" android:layout_alignParentBottom="true" android:layout_width="fill_parent" android:layout_height="wrap_content"/> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="0dp" android:layout_height="0dp"/> <FrameLayout android:id="@+id/content" android:layout_alignParentTop="true" android:layout_above="@android:id/tabs" android:layout_width="fill_parent" android:layout_height="fill_parent"/> </RelativeLayout> </android.support.v4.app.FragmentTabHost>
Activityの追加
public class MainActivity extends FragmentActivity { . . . @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /* ---------- START 追加部分 ---------- */ FragmentTabHost host = (FragmentTabHost) findViewById(android.R.id.tabhost); host.setup(this, getSupportFragmentManager(), R.id.content); TabSpec tabSpec1 = host.newTabSpec("tab1"); Button button1 = new Button(this); button1.setBackgroundResource(R.drawable.tab_left); tabSpec1.setIndicator(button1); Bundle bundle1 = new Bundle(); bundle1.putString("name", "Tab1"); host.addTab(tabSpec1, SampleFragment.class, bundle1); TabSpec tabSpec2 = host.newTabSpec("tab2"); Button button2 = new Button(this); button2.setBackgroundResource(R.drawable.tab_center); tabSpec2.setIndicator(button2); Bundle bundle2 = new Bundle(); bundle2.putString("name", "Tab2"); host.addTab(tabSpec2, SampleFragment.class, bundle2); TabSpec tabSpec3 = host.newTabSpec("tab3"); Button button3 = new Button(this); button3.setBackgroundResource(R.drawable.tab_right); tabSpec3.setIndicator(button3); Bundle bundle3 = new Bundle(); bundle3.putString("name", "Tab3"); host.addTab(tabSpec3, SampleFragment.class, bundle3); /* ---------- END 追加部分 ---------- */ } . . . }
Fragment内での子Fragmentにタブを表示
レイアウトは上記のものと変わらないのですが、Fragmentに追加するコードのhost.setup( ... );の部分一行を変更する必要があります。
getActivity()
とgetChildFragmentManager()
を使用します。
Fragmentの追加
public class BlankFragment extends Fragment { . . . @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_blank, container, false); /* ---------- START 追加部分 ---------- */ FragmentTabHost host = (FragmentTabHost) view.findViewById(android.R.id.tabhost); // 「getActivity()」、「getChildFragmentManager()」を使用 host.setup(getActivity(), getChildFragmentManager(), R.id.content); TabSpec tabSpec1 = host.newTabSpec("tab1"); Button button1 = new Button(this); button1.setBackgroundResource(R.drawable.tab_left); tabSpec1.setIndicator(button1); Bundle bundle1 = new Bundle(); bundle1.putString("name", "Tab1"); host.addTab(tabSpec1, SampleFragment.class, bundle1); TabSpec tabSpec2 = host.newTabSpec("tab2"); Button button2 = new Button(this); button2.setBackgroundResource(R.drawable.tab_center); tabSpec2.setIndicator(button2); Bundle bundle2 = new Bundle(); bundle2.putString("name", "Tab2"); host.addTab(tabSpec2, SampleFragment.class, bundle2); TabSpec tabSpec3 = host.newTabSpec("tab3"); Button button3 = new Button(this); button3.setBackgroundResource(R.drawable.tab_right); tabSpec3.setIndicator(button3); Bundle bundle3 = new Bundle(); bundle3.putString("name", "Tab3"); host.addTab(tabSpec3, SampleFragment.class, bundle3); /* ---------- END 追加部分 ---------- */ return view; } . . . }
参考サイト:
Android Tips #38 FragmentTabHost を使って Fragment をタブで切り替える | Developers.IO
【Android】HTTP通信でGET/POSTをする方法
HTTP通信でデータをGET/POSTをする場合の処理です。
HTTP通信をする場合、非同期処理をしないといけないので注意して下さい。
GET
HttpClient client = new DefaultHttpClient(); // パラメータの設定 ArrayList<NameValuePair> value = new ArrayList<NameValuePair>(); value.add( new BasicNameValuePair("key1", "value1")); value.add( new BasicNameValuePair("key2", "value2")); value.add( new BasicNameValuePair("key3", "value3")); String responseData = null; try { String query = URLEncodedUtils.format(value, "UTF-8"); HttpGet get = new HttpGet("URL" + "?" + query); // リクエスト送信 HttpResponse response = client.execute(get); // 取得 HttpEntity entity = response.getEntity(); responseData = EntityUtils.toString(entity, "UTF-8"); } catch(IOException e) { e.printStackTrace(); }
POST
HttpClient client = new DefaultHttpClient(); HttpPost post = new HttpPost("URL"); // パラメータの設定 ArrayList<NameValuePair> value = new ArrayList<NameValuePair>(); value.add( new BasicNameValuePair("key1", "value1")); value.add( new BasicNameValuePair("key2", "value2")); value.add( new BasicNameValuePair("key3", "value3")); String responseData = null; try { post.setEntity(new UrlEncodedFormEntity(value, "UTF-8"));// 文字コード変換 // リクエスト送信 HttpResponse response = client.execute(post); // 取得 HttpEntity entity = response.getEntity(); responseData = EntityUtils.toString(entity, "UTF-8"); } catch(IOException e) { e.printStackTrace(); }
参考サイト:
Androidでサーバと通信する方法(Asynctaskによる非同期HTTP通信) | Tech Booster
【Android】LoaderCallbacksで使用するLoaderManagerのAPIまとめ
AsyncTaskLoader
のコールバック処理であるLoaderCallbacks
ですが、それに使うLoaderManager
についてよく分からなかったので、まとめてみます。
Activity.getLoaderManager
複数のLoaderを管理するLoaderManagerのインスタンスを取得
- 各Activity/FragmentにLoaderManagerは1つ割り当てられ、何度コールしても同じLoaderManagerインスタンスが返却される
- Activity/Fragmentのインスタンスが異なれば返却されるLoaderManagerのインスタンス は異なるため、LoaderのID重複は気にする必要はない
- LoaderManagerはgetLoaderManagerメソッドの初回コール時に生成される
- LoaderManagerのライフサイクルはActivity/Fragmentにより管理され、onStart時に開始される
- ※onStart時にLoaderManagerが初期化(getLoaderManagerが呼ばれていない)されていなければLoaderManagerは正しく動作しない
- getLoaderManagerメソッドはonStartより前にコールしないと、LoaderManagerがLoaderを正しく管理してくれない
LoaderManager.initLoader
指定したIDでLoaderを初期化・生成
- 指定するIDはLoaderの識別子として使用され、Loaderが作成される時はonCreateLoaderがコールバックされる
- initLoaderは指定のLoaderを初期化
- 指定したIDに紐づくLoaderがすでに存在している場合、Loaderは初期化されない
- Loaderへのコールバックが指定されたインスタンスでは上書きされる
- このとき、引数のargsは無視される
- initLoaderは関連するActivityのonCreateまたはFragmentのonCreateActivityに使用されるべきメソッド
- LoaderManagerはconfiguration changeによって破棄・生成されず再利用される
- LoaderManagerは既に存在するLoaderの再利用を可能としている
- Activityがconfiguration changeにより再生成されてonCreateでinitLoaderを コールしても、対象のLoaderをLoaderManagerが既に保持しているのでLoaderを生成する onCreateLoaderが再度呼ばれることはない
- 注意点として、Loaderが再利用される場合は引数argsは無視される
LoaderManager.restartLoader
引数のIDに関連付けられているLoaderを再生成
- 既存のLoaderは必要に応じてキャンセル/停止/破棄される
- 生成されるLoaderは引数argsを持つ新たなLoaderとして生成される
LoaderManager.destroyLoader
引数のIDに紐づいたLoaderを停止・破棄
- 破棄対象のLoaderがデータをユーザへ通知していた場合は、onLoadFinishedから onLoaderResetがコールされる
参考サイト: