1

いくつかの領域で構成されるメッセンジャー アプリを計画しています。

  • ログインサインアップ
  • 連絡先リスト
  • 会話
  • オンライン ステータスの選択 (オンライン、離席中、DND など)
  • 設定

スマートフォンでは、一度に 1 つのアクティビティしか存在しないはずですが、タブレットにはショートカット付きのサイドバーが必要です (連絡先リストを表示する会話ビューでは、設定カテゴリのリストを表示する設定で)。

私の理解では、これらの領域はフラグメントであり、1 つまたは複数のアクティビティに挿入されます。

そこで、次のレイアウト (res/main.xml) でアクティビティの作成を開始しました。

<?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:orientation="vertical" >

    <fragment
        android:id="@id/main_fragment_focus"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

および対応するタブレット レイアウト: (layout-large-land/main.xml)

<?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:orientation="horizontal" >

        <fragment
            android:id="@id/main_fragment_sidebar"
            android:layout_width="@dimen/main_sidebar_width"
            android:layout_height="match_parent" />

            <fragment
        android:id="@id/main_fragment_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

ここまでは順調ですね。少なくとも私が思った限り。そこで、単純なアクティビティを作成しました。API レベル 5+ との互換性を提供したいので、ActionBarSherlock を使用しています。

package com.pm.messenger;

import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.util.Log;

import com.actionbarsherlock.app.SherlockFragmentActivity;

public class PMMessengerActivity extends SherlockFragmentActivity {

    // -------------------------------------------------------------------------

    FragmentManager fragmentManager = null;

    // -------------------------------------------------------------------------

    public void onCreate(Bundle savedInstanceState) {

        // ---------------------------------------------------------------------

        super.onCreate(savedInstanceState);

        // ---------------------------------------------------------------------

        fragmentManager = getSupportFragmentManager();

        // ---------------------------------------------------------------------

        if (savedInstanceState == null) {

            // -----------------------------------------------------------------



            // -----------------------------------------------------------------

        }
        else {

            // -----------------------------------------------------------------



            // -----------------------------------------------------------------

        }

        // ---------------------------------------------------------------------

        Log.d(getClass().getSimpleName(), "no problem before setContentView");

        setContentView(R.layout.main);

        Log.d(getClass().getSimpleName(), "no problem after setContentView");

        // ---------------------------------------------------------------------

    }

    // -------------------------------------------------------------------------

}

これを実行すると、アプリがすぐにクラッシュします。最初に、これは FragmentManager-FragmentTransactions を提供しなかったために発生すると考えましたが、(Log.d-Lines を挿入した後) SetContentView の呼び出し中にクラッシュが発生することに気付きました。

LogCat 出力:

01-24 16:58:26.728: I/ActivityManager(667): START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.pm.messenger/.pmMessengerActivity bnds=[912,542][1008,638]} from pid 877
01-24 16:58:26.748: D/dalvikvm(26431): Late-enabling CheckJNI
01-24 16:58:26.758: I/ActivityManager(667): Start proc com.pm.messenger for activity com.pm.messenger/.pmMessengerActivity: pid=26431 uid=10009 gids={3003, 1015}
01-24 16:58:26.778: E/jdwp(26431): Failed sending reply to debugger: Broken pipe
01-24 16:58:26.778: D/dalvikvm(26431): Debugger has detached; object registry had 1 entries
01-24 16:58:26.788: D/OpenGLRenderer(877): Flushing caches (mode 1)
01-24 16:58:26.828: D/pmMessengerActivity(26431): no problem before setContentView
01-24 16:58:26.858: D/AndroidRuntime(26431): Shutting down VM
01-24 16:58:26.858: W/dalvikvm(26431): threadid=1: thread exiting with uncaught exception (group=0x40a3e1f8)
01-24 16:58:26.868: D/OpenGLRenderer(877): Flushing caches (mode 0)
01-24 16:58:26.868: E/AndroidRuntime(26431): FATAL EXCEPTION: main
01-24 16:58:26.868: E/AndroidRuntime(26431): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.pm.messenger/com.pm.messenger.pmMessengerActivity}: android.view.InflateException: Binary XML file line #7: Error     inflating class fragment
01-24 16:58:26.868: E/AndroidRuntime(26431):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at android.app.ActivityThread.access$600(ActivityThread.java:123)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at android.os.Handler.dispatchMessage(Handler.java:99)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at android.os.Looper.loop(Looper.java:137)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at android.app.ActivityThread.main(ActivityThread.java:4424)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at java.lang.reflect.Method.invokeNative(Native Method)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at java.lang.reflect.Method.invoke(Method.java:511)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at dalvik.system.NativeStart.main(Native Method)
01-24 16:58:26.868: E/AndroidRuntime(26431): Caused by: android.view.InflateException: Binary XML file line #7: Error inflating class fragment
01-24 16:58:26.868: E/AndroidRuntime(26431):    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:697)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at android.view.LayoutInflater.rInflate(LayoutInflater.java:739)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:251)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at com.actionbarsherlock.internal.ActionBarSherlockNative.setContentView(ActionBarSherlockNative.java:119)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at com.actionbarsherlock.app.SherlockFragmentActivity.setContentView(SherlockFragmentActivity.java:262)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at com.pm.messenger.pmMessengerActivity.onCreate(pmMessengerActivity.java:48)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at android.app.Activity.performCreate(Activity.java:4465)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
01-24 16:58:26.868: E/AndroidRuntime(26431):    ... 11 more
01-24 16:58:26.868: E/AndroidRuntime(26431): Caused by: java.lang.NullPointerException: name == null
01-24 16:58:26.868: E/AndroidRuntime(26431):    at java.lang.VMClassLoader.findLoadedClass(Native Method)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at java.lang.ClassLoader.findLoadedClass(ClassLoader.java:354)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at java.lang.ClassLoader.loadClass(ClassLoader.java:491)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at android.support.v4.app.Fragment.instantiate(Fragment.java:381)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at android.support.v4.app.Fragment.instantiate(Fragment.java:359)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:262)
01-24 16:58:26.868: E/AndroidRuntime(26431):    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:669)
01-24 16:58:26.868: E/AndroidRuntime(26431):    ... 22 more
01-24 16:58:26.868: W/ActivityManager(667):   Force finishing activity com.pm.messenger/.pmMessengerActivity
01-24 16:58:27.408: W/ActivityManager(667): Activity pause timeout for ActivityRecord{410d8c98 com.pm.messenger/.pmMessengerActivity}

このクラッシュは、XML でフラグメントクラスを静的に提供しなかったことが原因だと思いますが、これを使用したくありません。これを動的な方法で実現したいと考えています。

XML でクラスを静的に提供する必要がある場合、複数のアクティビティ (LoginActivity、SignupActivity、ContactListActivity、ConversationActivity など) も必要だと思いますが、やめてください。これは正しくありません。フラグメントが存在する権利を失うためです。私見では。

私の理解では、フラグメントは私のアプリの孤立した部分であり、当時のアクティビティのような機能の領域を実装しています。これらは、バックスタックを管理するコンテナー アクティビティに埋め込まれます。

では、私の論理のどこに問題があるのでしょうか? フラグメントの代わりに FrameView のレイアウトを使用する必要がありますか? わからない。

また、動的フラグメント管理に関する、適切で理解しやすく、十分に文書化されたリソースが見つかりません。

4

2 に答える 2

1

あなたの特定のエラーは、明らかに存在しないフラグメントを膨らませようとしているという事実によるものです。動的フラグメントの場合、静的レイアウトに FrameLayout を配置し、実行時にフラグメントをそれらのフレームに配置する必要があります。レイアウトの例を次に示します。

<?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" >

<View
    android:id="@+id/anchor"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:layout_centerInParent="true" />

<FrameLayout
    android:id="@+id/top_left"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:layout_above="@+id/anchor"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:layout_toLeftOf="@+id/anchor">

</FrameLayout>

<FrameLayout
    android:id="@+id/top_right"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:layout_above="@+id/anchor"
    android:layout_alignParentRight="true"
    android:layout_alignParentTop="true"
    android:layout_toRightOf="@+id/anchor">

</FrameLayout>

<FrameLayout
    android:id="@+id/bottom_left"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_below="@+id/anchor"
    android:layout_toLeftOf="@+id/anchor">

</FrameLayout>

<FrameLayout
    android:id="@+id/bottom_right"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:layout_alignParentBottom="true"
    android:layout_alignParentRight="true"
    android:layout_below="@+id/anchor"
    android:layout_toRightOf="@+id/anchor">

</FrameLayout>

</RelativeLayout> 

これは、同じサイズの 4 つの FrameLayout をグリッドに配置する場合に起こります。これを使用して、実行時にフラグメントを追加できます。

    Fragment levelsF = Fragment.instantiate(this, 
LevelsFragment.class.getName());
    Fragment waveF = Fragment.instantiate(this,
WaveFragment.class.getName());
    Fragment lightF = Fragment.instantiate(this,    
LightPlayerFragment.class.getName());
    Fragment keyboardF = Fragment.instantiate(this,
KBFragment.class.getName());

    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    ft.add(R.id.top_left, levelsF);
    ft.add(R.id.top_right, waveF);
    ft.add(R.id.bottom_left, lightF);
    ft.add(R.id.bottom_right, keyboardF);     
    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    ft.commit();
    getSupportFragmentManager().executePendingTransactions();

静的フラグメントが必要ない場合は、xml でそれらをまったく参照しないでください。

于 2013-01-24T16:26:34.503 に答える
0

Androidには、APIに関するすばらしいドキュメントがあります。Fragmentクラスのライフサイクルとメソッドを明確に説明しています。お役に立てれば。 フラグメントのドキュメント

于 2013-01-24T16:16:34.363 に答える