Androidプログラミング権威ガイド(第2版)学習ノート(十七)-第17章Master-Detailユーザーインタフェース
6460 ワード
この章では,2面fragmentのレイアウトをどのように書くかを紹介し,要求に合致するデバイスを適切に配置し,コールバックインタフェースの使用も紹介した.GitHubアドレス:完成17章
タブレットデバイスにとって、ユーザーインタフェースからプライマリを使用するとより良い体験が得られます.この章では、データを伝達する方法を探究します.
1.レイアウトの柔軟性を高める
2ページレイアウトを実現するには、次のタスクを実行する必要があります. SingleFragmentActivityを変更し、ハードコーディングされていないインスタンス化レイアウト を修正する.は、2つのfragmentコンテナを含むレイアウト を作成する. CrimeListActivityを修正し、携帯電話機器で単面レイアウトをインスタンス化し、タブレット機器で二面レイアウトをインスタンス化する を実現する.
1.1抽象クラスSingleFragmentActivityの変更
ここにprotectedメソッドを追加して、SingleFragmentActivityを継承するactivityに対して、必要なResIdを返すために関数を書き換えることができます.
1.2別名リソースの使用
最小スクリーン幅600 dpのデバイスに2面インタフェースを使用させ,他のデバイスに1面インタフェースを使用させると,異なるデバイスに対して使用レイアウトが異なる.異なるデバイスに異なるレイアウトリソースを使用させるには、次の2つの方法があります. res/layout/ディレクトリ内のファイルにリソース修飾子を使用させます. 別名リソースを使用します.別名リソースは、他のリソースを指す特殊なリソースです.res/values/ディレクトリに格納され、refs.xmlファイルに約束通りに定義されます.例えば、デフォルトのvaluesフォルダの下にrefs.xmlを新規作成し、コードを書き込む: になる.
2.Activity:Fragmentの管理者
fragmentの独立性を保証するために、管理者の仕事を理解する必要はありませんが、fragmentのライフサイクルが終了していないときにデータを渡すには、コールバックインタフェースを使用します.
コールバックは依頼に相当し、まずfragmentがコールバックのインタフェースを自分で定義し、管理されたacitivityがこのインタフェースを実現し、fragmentは自分で定義したインタフェースを実現したオブジェクトを持って、自分がリアルタイムで呼び出すことができるようにする必要がある.
1つのコールバックインタフェースにとってfragmentは、このインタフェースを実現するクラスが関数の中で何をしなければならないのかだけを要求しているが、実現クラスが何をするのか分からない.各実現クラスには独自の方法がある.
2.1 CrimeListFragmentのコールバックインタフェース
CrimeListFragmentでは、リストのいずれかをクリックすると、コールバックインタフェースの定義は次のようになります.
次に、CrimeListActivity:
CrimeListFragmentに実装インタフェースのactivityのリファレンスを保持し、メモリの回収のためにライフサイクルの最後にリファレンスを除去します.
最後にonClickイベントを変更し、mCallbacks.onCrimeSelected(Crime crime)を呼び出せばよい.これにより、ダブルレイアウトビューでリストのいずれかをクリックすると、詳細レイアウトに該当する情報が表示されます.
しかし、1つの問題は、詳細ページ(CrimeFragment)で情報を変更し、リストページでは何の応答もなく、CrimeListFragmentは一時停止しないのでリフレッシュもしないので、次はCrimeFragmentでコールバックインタフェースを定義し、管理activityにCrimeListFragmentを更新させることです.
2.2 CrimeFragmentのコールバックインタフェース
まずコールバックインタフェースを定義します.ここで管理者にしてもらいたいのは、Crimeの詳細が更新されたときにリストを更新することです.
このインタフェースは、CrimeListActivityで実装されます.
CrimeFragmentを管理するactivityはコールバックインタフェースを実装すべきであるため、CrimePagerActivityに空のインタフェース実装を提供する
その後、データが変更されるたびに
3.チャレンジの後遺症:クリムの削除
私たちがToolBarの章で加わった挑戦を覚えていますか.Crimeを削除することです.CriminalIntentというアプリケーションでは、2面と1面の削除操作には異なる結果があるはずですが、これらの行為は本に定義されていないので、次の補充プログラムを書く方法を確立するために、自分で解決策を考えています.の2面の画面の下で、左のリストから削除すべき項目を削除するにはクリックし、詳細ページもすでに存在するいずれかの詳細に変更し、実現を容易にするために、ここではすでに存在する最初の項目に変更します.最後の項目だけが削除されている場合は、右側が空白になるはずです. 単面の画面の下で、削除をクリックして直接このレコードを削除し、activityを終了します.
ここではCrimeFragmentのCallbacksインタフェースにonCrimeDelete(Crime crime)メソッドとonCrimeAllDeleted(Crime crime)メソッドを加え、CrimeListActivityでは以下のように実現しています.
CrimePagerActivityでもこの2つの方法を実現するが,このactivityではfinish()を行えばよい.
「≪削除|Delete|Essbase_Studio≫」ボタンの選択したリスナーで、次の操作を行います.
これでプログラム全体が完成しました~
GitHub Page: kniost.github.io :http://www.jianshu.com/u/723da691aa42
タブレットデバイスにとって、ユーザーインタフェースからプライマリを使用するとより良い体験が得られます.この章では、データを伝達する方法を探究します.
1.レイアウトの柔軟性を高める
2ページレイアウトを実現するには、次のタスクを実行する必要があります.
1.1抽象クラスSingleFragmentActivityの変更
ここにprotectedメソッドを追加して、SingleFragmentActivityを継承するactivityに対して、必要なResIdを返すために関数を書き換えることができます.
@LayoutRes
protected int getLayoutResId() {
return R.layout.activity_fragment;
}
1.2別名リソースの使用
最小スクリーン幅600 dpのデバイスに2面インタフェースを使用させ,他のデバイスに1面インタフェースを使用させると,異なるデバイスに対して使用レイアウトが異なる.異なるデバイスに異なるレイアウトリソースを使用させるには、次の2つの方法があります.
activity_masterdetail.xml
レイアウトファイルを使用する場合は、activity_fragment.xml
のコンテンツをres/layout/activity_masterdetail.xml
にコピーし、activity_twopane.xml
のコンテンツをres/layout-sw600dp/activity_masterdetail.xml
にコピーする必要があります.このような最も明らかな欠点は、レイアウトファイルごとにコピーされるため、データ冗長性です.
- @layout/activity_fragment
最小幅600 dpのrefs.xml(values-sw 600 dpディレクトリの下)を新規作成し、2面のlayoutリソース:
- @layout/activity_twopane
を書き込む.これにより、CrimeListActivityではR.layout.activity_masterdetail
を参照すれば2.Activity:Fragmentの管理者
fragmentの独立性を保証するために、管理者の仕事を理解する必要はありませんが、fragmentのライフサイクルが終了していないときにデータを渡すには、コールバックインタフェースを使用します.
コールバックは依頼に相当し、まずfragmentがコールバックのインタフェースを自分で定義し、管理されたacitivityがこのインタフェースを実現し、fragmentは自分で定義したインタフェースを実現したオブジェクトを持って、自分がリアルタイムで呼び出すことができるようにする必要がある.
1つのコールバックインタフェースにとってfragmentは、このインタフェースを実現するクラスが関数の中で何をしなければならないのかだけを要求しているが、実現クラスが何をするのか分からない.各実現クラスには独自の方法がある.
2.1 CrimeListFragmentのコールバックインタフェース
CrimeListFragmentでは、リストのいずれかをクリックすると、コールバックインタフェースの定義は次のようになります.
public interface Callbacks {
void onCrimeSelected(Crime crime);
}
次に、CrimeListActivity:
// implement
@Override
public void onCrimeSelected(Crime crime) {
// fragment id,
// activity
if (findViewById(R.id.detail_fragment_container) == null) {
Intent intent = CrimePagerActivity.newIntent(this, crime.getId());
startActivity(intent);
} else {
// detail fragment
Fragment newDetail = CrimeFragment.newInstance(crime.getId());
getSupportFragmentManager().beginTransaction()
.replace(R.id.detail_fragment_container, newDetail)
.commit();
}
}
CrimeListFragmentに実装インタフェースのactivityのリファレンスを保持し、メモリの回収のためにライフサイクルの最後にリファレンスを除去します.
// CrimeListFragment
private Callbacks mCallbacks;
@Override
public void onAttach(Context context) {
super.onAttach(context);
mCallbacks = (Callbacks) context;
}
// ……
@Override
public void onDetach() {
super.onDetach();
mCallbacks = null;
}
最後にonClickイベントを変更し、mCallbacks.onCrimeSelected(Crime crime)を呼び出せばよい.これにより、ダブルレイアウトビューでリストのいずれかをクリックすると、詳細レイアウトに該当する情報が表示されます.
しかし、1つの問題は、詳細ページ(CrimeFragment)で情報を変更し、リストページでは何の応答もなく、CrimeListFragmentは一時停止しないのでリフレッシュもしないので、次はCrimeFragmentでコールバックインタフェースを定義し、管理activityにCrimeListFragmentを更新させることです.
2.2 CrimeFragmentのコールバックインタフェース
まずコールバックインタフェースを定義します.ここで管理者にしてもらいたいのは、Crimeの詳細が更新されたときにリストを更新することです.
// CrimeFragment
private Callbacks mCallbacks;
public interface Callbacks {
void onCrimeUpdated(Crime crime);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mCallbacks = (Callbacks) context;
}
// ……
@Override
public void onDetach() {
super.onDetach();
mCallbacks = null;
}
このインタフェースは、CrimeListActivityで実装されます.
@Override
public void onCrimeUpdated(Crime crime) {
CrimeListFragment listFragment = (CrimeListFragment)
getSupportFragmentManager()
.findFragmentById(R.id.fragment_container);
listFragment.updateUI();
}
CrimeFragmentを管理するactivityはコールバックインタフェースを実装すべきであるため、CrimePagerActivityに空のインタフェース実装を提供する
その後、データが変更されるたびに
mCallbacks.onCrimeUpdated(mCrime);
を呼び出せばよい.本には更新モデル層も一緒に置かれている.3.チャレンジの後遺症:クリムの削除
私たちがToolBarの章で加わった挑戦を覚えていますか.Crimeを削除することです.CriminalIntentというアプリケーションでは、2面と1面の削除操作には異なる結果があるはずですが、これらの行為は本に定義されていないので、次の補充プログラムを書く方法を確立するために、自分で解決策を考えています.
ここではCrimeFragmentのCallbacksインタフェースにonCrimeDelete(Crime crime)メソッドとonCrimeAllDeleted(Crime crime)メソッドを加え、CrimeListActivityでは以下のように実現しています.
@Override
public void onCrimeDeleted(Crime crime) {
// , Crime ,
// Crime, Crime
onCrimeSelected(crime);
}
@Override
public void onCrimeAllDeleted(Crime crime) {
// , fragment
CrimeFragment fragment = (CrimeFragment)
getSupportFragmentManager()
.findFragmentById(R.id.detail_fragment_container);
if (fragment != null) {
getSupportFragmentManager()
.beginTransaction()
.remove(fragment)
.commit();
}
//
onCrimeUpdated(crime);
}
CrimePagerActivityでもこの2つの方法を実現するが,このactivityではfinish()を行えばよい.
「≪削除|Delete|Essbase_Studio≫」ボタンの選択したリスナーで、次の操作を行います.
CrimeLab.get(getActivity()).deleteCrime(mCrime);
if (CrimeLab.get(getActivity()).getCrimes().isEmpty()) {
mCallbacks.onCrimeAllDeleted(mCrime);
} else {
mCrime = CrimeLab.get(getActivity()).getCrimes().get(0);
mCallbacks.onCrimeDeleted(mCrime); //
updateCrime(); //
}
return true;
これでプログラム全体が完成しました~
GitHub Page: kniost.github.io :http://www.jianshu.com/u/723da691aa42