0

次のアプリケーションレイアウトがあります。LinearLayoutでListViewをホストするFragmentをホストするLinearLayoutを使用したアクティビティ。ListViewの表示方法をテンプレート化しました(正しい用語かどうかはわかりませんが、WPFから来ています)。常に表示される3行の部分と、アイテムがクリックされたときに展開されるViewStubがあります(常に1つのアイテムのみが展開されます)。

各ListViewアイテムを最初にクリックすると、スタブが膨らみ(すべてのアイテムで機能します)、詳細とmyButtonコントロールが構成されます。これはすべてのListViewアイテムで機能しますが、最後のアイテムでは、detailsとmyButtonが表示されることはありません。その上、別のスタブが展開されると、最後のListViewアイテムが非表示になります。つまり、現在展開されているアイテム用のスペースを作るために下に移動するのではありません。

したがって、myListView.Items.Count -1の位置にあるListViewアイテムをクリックしても、展開は何も表示されません。他のListViewアイテムをクリックすると、最後のListViewアイテムが消えます。

これがフラグメントのレイアウトです

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:minWidth="25px"
android:minHeight="25px">
<TextView
    android:text="@string/active_calls"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@+id/Calls_Header" />
<ListView
    android:minWidth="25px"
    android:minHeight="25px"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@+id/ActiveCallsList" />
</LinearLayout>

そして、各ListViewアイテムのレイアウト

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TableLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@+id/tableLayout1"
    android:shrinkColumns="*"
    android:stretchColumns="*">
    <TableRow
        android:id="@+id/tableRow1">
        <TextView
            android:text="Caller Name"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:id="@+id/CallerName"
            android:layout_column="0"
            android:layout_span="2" />
    </TableRow>
    <TableRow
        android:id="@+id/tableRow2">
        <TextView
            android:text="+41 12 345 6789"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:id="@+id/CallerNumber"
            android:layout_column="0" />
        <TextView
            android:text="00:01:25"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:id="@+id/CallDuration"
            android:layout_column="1" />
    </TableRow>
    <TableRow
        android:id="@+id/tableRow3">
        <TextView
            android:text="Ringing"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:id="@+id/CallStatus"
            android:layout_column="0" />
    </TableRow>
</TableLayout>
<ViewStub
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@+id/viewStub1" 
    android:inflatedId="@+id/CallDetails"
    android:layout="@layout/CallDetails" />
</LinearLayout>

と拡張する部分

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
    android:text="Text"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@+id/CallDetailsText" />
<Button
    android:text="@string/endCall"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@+id/EndCallButton" />
</LinearLayout>

そして、BaseAdapterから派生したArrayAdapterの私自身の実装に関連付けられたItemClickハンドラー。

void calls_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
    {
        if (inflatedView != null)
            inflatedView.Visibility = ViewStates.Gone; // make sure only one item is inflated at all times

        var obj = e.Parent.GetItemAtPosition(e.Position);
        var listView = sender as ListView;
        Model.Call t = Model.Calls.MyCalls[e.Position];
        string text = t.CallerName + " " + t.CallState;

        Log.Debug("SmartAppMobile", "Call " + text + " clicked");

        //Toast.MakeText(this.Activity, text, ToastLength.Short).Show();
        ViewStub myStub = e.View.FindViewById<ViewStub>(Resource.Id.viewStub1);

        bool previouslyFound = false;
        if (myStub != null)
        {
            inflatedView = myStub.Inflate();
        }
        else
        {
            Log.Debug("myapp", "View stub not found for " + text);
            inflatedView = e.View.FindViewById<View>(Resource.Id.CallDetails);
            inflatedView.Visibility = ViewStates.Visible;
            previouslyFound = true;
        }

        TextView details = inflatedView.FindViewById<TextView>(Resource.Id.CallDetailsText);
        if (details != null)
            details.Text = "Call details go here... " + t.CallerNumber;
        else
            Log.Debug("myapp", "Call Details Text field not found for " + text);
        Button myButton = inflatedView.FindViewById<Button>(Resource.Id.EndCallButton);
        if (myButton != null)
        {
            if (!previouslyFound)
                myButton.Click += (x, y) =>
                {
                    Model.Calls.MyCalls.Remove(t);
                    //((ArrayAdapter)listView.Adapter).NotifyDataSetChanged();
                    inflatedView.Visibility = ViewStates.Gone;
                };
        }
    }

また、myButtonをクリックすると、アプリケーションは電話の戻るボタンを押したかのように反応します。ListViewアイテムは、コードで追加したものである場合にのみ削除されます。

したがって、フラグメントをホストしているアクティビティを呼び出す方法と、ListViewアイテムがバインドされる方法を追加する必要があると思います。

ListViewをホストしている私のフラグメントでは:

    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View fragment = inflater.Inflate(Resource.Layout.CallsFragment, null);
        calls = fragment.FindViewById<ListView>(Resource.Id.ActiveCallsList);
        calls.Adapter = new ActiveCallsAdapter(this.Activity, Model.Calls.MyCalls);
        calls.ItemClick += new EventHandler<AdapterView.ItemClickEventArgs>(calls_ItemClick);

        return fragment;
    }

と私のデータモデルの呼び出し

public class Calls
{

    private static List<Call> myCalls;

    private static object myLock = new object();

    public static List<Call> MyCalls
    {
        get 
        {
            lock (myLock)
            {
                if (myCalls != null)
                    return myCalls;
                myCalls = new List<Call>();
                myCalls.Add(new Call { CallerName = "some name", CallerNumber = "some phone number", CallState = Model.CallState.Init });
                myCalls.Add(new Call { CallerName = "some other name", CallerNumber = "another number", CallState = CallState.Held });
                return myCalls;
            }
        }
    }

}

そして、リストに新しいアイテムを追加してリストを表示するためにメインアクティビティで使用するボタン:

Button button = FindViewById<Button> (Resource.Id.myButton);
        button.Click += delegate 
        {
            button.Text = string.Format ("{0} clicks!", count++);
            Model.Calls.MyCalls.Add(new Model.Call { CallerName = "test " + count, CallerNumber = "" + count, CallState = Model.CallState.Active });
            StartActivity(new Intent(this, typeof(CallsActivity)));
        };

そしてもちろん、CallsActivity

[Activity(Label = "My Activity")]
public class CallsActivity : Activity
{
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
        SetContentView(Resource.Layout.CallsActivity);
        // Create your application here
    }
}
4

1 に答える 1

0

これはレイアウトのバグです。選択した通話を膨らませると、通話レイアウトは大きくなりますが、親は大きくなりません。そのため、一番下の通話は端から外れます。これが、下部のコンテンツが拡張されていないように見える理由でもあります。拡張されたコンテンツは下部から落ちています。CallDetails.axmlを編集してボタンのlayout_heightを1dpに設定すると、これが実際に動作していることがわかります。

このレイアウトの問題を修正するには、activeCallsList / layout_height(CallsFragment.axml内)をwrap_contentではなくmatch_parentまたはfill_parentに変更します。activeCallsListは、最初に描画されたときに呼び出しを表示するのに十分なスペースを予約する代わりに、できるだけ多くのスペースを予約します。これにより、コールビューが期待どおりに動作します。

-最大

于 2012-08-18T18:11:38.590 に答える