我有一个使用操作栏的选项卡功能托管多个片段的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