我有一個使用操作欄的選項卡功能託管多個片段的Activity。其中一個片段包含一個ListView。在選中此選項卡後,我想選擇某個項目。Android:在onResume中選擇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);
}
}
如果你需要使用'PerformItemClick'(單聲道),我認爲你不能沒有延遲的行動。在hack類別中,你還可以在'ListView'上發佈一個'postn'發佈的'Runnable'(並在那裏調用'PerformItemClick')。如果我在您的位置,我只需更改適配器以使其具有擴展項目並直接調用的方法。 – Luksprog
正如你從我不完整的代碼清理中猜到的,我正在使用Mono4Android。 – user1537915
我不熟悉Mono for Android(所以可能有一些限制,我不知道),但我會改變適配器,就像我上面說的,而不是使用'performClick'方法。 – Luksprog