アクションバーのタブ機能を使用して複数のフラグメントをホストするアクティビティがあります。それらのフラグメントの1つにListViewが含まれています。このタブを選択したら、特定の項目を選択したいと思います。
これをプログラムで行うには、次のコードを使用します(呼び出しはListViewです)
private void selectItem(int position)
{
long itemId = calls.GetItemIdAtPosition(position);
calls.PerformItemClick(calls, position, itemId);
}
このListViewがレンダリングされていて、これを呼び出している場合は、問題ありません。ただし、onResumeから呼び出すと、コードは実行されますが、最後には何も選択されません。これは、selectItemを呼び出している時点で、ListViewのすべてのアイテムがまだレンダリングされていないためだと思います。ただし、バックグラウンドスレッドから開始し、数百ミリ秒スリープしてから、同じコードを実行すると(もちろん、UIスレッドで)、すべて問題ありませんが、これは醜いハックです。
「なぜ彼はcalls.setSelectionを使用しないのか」と疑問に思うかもしれません。重要なのは、拡張を実行するカスタムレイアウトを使用しているため、実際に選択するアイテムをクリックする必要があります(これにより、選択したアイテムのレイアウト拡張がトリガーされます)。ただし、PerformItemClickで実行されるコードを直接呼び出すことはできますが、結果は同じになります(レイアウト拡張は実行されません)。
「Listviewがすべての表示可能なアイテムのレンダリングを終了しました」という時点をキャッチし、その時点でselectItem呼び出しを実行する方法はありませんか?ASP.NETでは、すべてのUIアイテムに、レンダリングが完了したことを通知するイベントがあるため、その時点でアイテムの選択を行いますが、何も見つかりませんでした。
よろしくステファン
これが私が使用しているアダプターです
public class ActiveCallsAdapter: ObservableAdapter<Call>
{
public ActiveCallsAdapter(Activity activity, ObservableCollection<Call> calls)
: base(activity, calls)
{
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var item = items[position];
var view = (convertView ?? context.LayoutInflater.Inflate(Resource.Layout.Call, parent, false)) as LinearLayout;
//View view = convertView;
//if (view == null) // no view to re-use, create new
// view = context.LayoutInflater.Inflate(Resource.Layout.Call, null);
SetTextView(view, Resource.Id.CallerName, item.CallerName);
SetTextView(view, Resource.Id.CallerNumber, item.CallerNumber);
SetTextView(view, Resource.Id.CallStatus, item.State.ToString());
SetTextView(view, Resource.Id.CallDuration, item.Duration);
return view;
}
public void Update(LinearLayout view, Call item)
{
SetTextView(view, Resource.Id.CallerName, item.CallerName);
SetTextView(view, Resource.Id.CallerNumber, item.CallerNumber);
string identifier = "callState_" + item.State.ToString();
int resourceId = Application.Context.Resources.GetIdentifier(identifier, "string", Application.Context.PackageName);
string callStateString = item.State.ToString();
if (resourceId != 0)
{
try
{
callStateString = Application.Context.Resources.GetString(resourceId);
}
catch (Exception e)
{
AndroidLogModel.Model.AddLogMessage("ActiveCallsAdapter", "Unable to find call state string with resource id " + resourceId + " state string: " + identifier, 3);
}
}
SetTextView(view, Resource.Id.CallStatus, callStateString);
//SetTextView(view, Resource.Id.CallDuration, item.Duration);
}
public void UpdateDuration(LinearLayout view, Call item)
{
SetTextView(view, Resource.Id.CallDuration, item.Duration);
}
}
そして、そのアダプタの基本クラス
public class ObservableAdapter<T>: BaseAdapter<T>
{
protected readonly Activity context;
protected readonly ObservableCollection<T> items;
public ObservableAdapter(Activity context, ObservableCollection<T> collection)
{
this.context = context;
this.items = collection;
//this.collection.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(collection_CollectionChanged);
this.items.CollectionChanged += (sender, e) => NotifyDataSetChanged();
}
void collection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
NotifyDataSetChanged();
}
public override T this[int position]
{
get { return items[position]; }
}
public override int Count
{
get { return items.Count; }
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var item = items[position];
var view = (convertView ?? context.LayoutInflater.Inflate(Resource.Layout.Call, parent, false)) as LinearLayout;
// configure view here
return view;
}
protected void SetTextView(LinearLayout view, int id, string text)
{
var textView = view.FindViewById<TextView>(id);
if (textView != null)
textView.SetText(text, TextView.BufferType.Normal);
}
}