我有一个Activity,它使用操作栏的标签功能托管多个片段。其中一个片段包含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);
}
}
答案 0 :(得分:2)
我的单声道技能有限,所以我不知道我是否完全理解你的适配器,无论如何我已经改编了一些旧代码并制作了一个适配器,可以在单击时扩展单个项目,同时也会移动{{1} } ListView
到期望的位置:
onResume
private static class CustomAdapter extends BaseAdapter {
// the data
private ArrayList<String> mData;
// an int pointing to a position that has an expanded layout,
// for simplicity I assume that you expand only one item(otherwise use
// an array or list)
private int mExpandedPosition = -1; // -1 meaning no expanded item
private LayoutInflater mInflater;
public CustomAdapter(Context context, ArrayList<String> items) {
mInflater = LayoutInflater.from(context);
mData = items;
}
public void setExpandedPosition(int position) {
// if the position equals mExpandedPosition then we have a click on
// the same row so simply toggle the row to be gone again
if (position == mExpandedPosition) {
mExpandedPosition = -1;
} else {
// else change position of the row that was expanded
mExpandedPosition = position;
}
// notify the adapter
notifyDataSetChanged();
}
@Override
public int getCount() {
return mData.size();
}
@Override
public String getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.ad_expandedelement,
parent, false);
}
((TextView) convertView.findViewById(R.id.textView1))
.setText(getItem(position));
// see if there is an expanded position and if we are at that
// position
if (mExpandedPosition != -1 && mExpandedPosition == position) {
// if yes simply expand the layout
convertView.findViewById(R.id.button1).setVisibility(
View.VISIBLE);
} else {
// this is required, we must revert any possible changes
// otherwise the recycling mechanism will hurt us
convertView.findViewById(R.id.button1).setVisibility(View.GONE);
}
return convertView;
}
}
只会是:
onListItemClick
并且在@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// set the expanded(or collapsed if it's a click on the same row that
// was previously expanded) row in the adapter
((CustomAdapter) getListView().getAdapter())
.setExpandedPosition(position);
}
中会有:
onResume
@Override
protected void onResume() {
super.onResume();
// set the position to the desired element
((CustomAdapter) getListView().getAdapter()).setExpandedPosition(15);
// set the selection to that element so we can actually see it
// this isn't required but has the advantage that it will move the
// ListView to the desired
// position if not visible
getListView().setSelection(15);
}
是一个简单的垂直R.layout.ad_expandedelement
,LinearLayout
,最初隐藏(知名度设置为已消失)TextView
。对于此Button
,我更改了可见性,以模拟在Button
中展开/折叠行。您应该能够理解我的代码,如果您愿意,我可以在github上发布完整的样本。
答案 1 :(得分:1)
虽然我不确定C#/ Mono中的确切等效内容,但Android框架会在名为Activity
的{{1}}上提供一个回调,指示与onWindowFocusChanged()
关联的时间段给定Window
对用户可见。你可能有更好的运气等到你的选择方法,直到那个时候,因为Activity
应该被测量和布置。在Java中,它将是这样的:
ListView
你可能需要更多逻辑,这个回调与窗口焦点直接相关,并不是真正的生命周期方法。如果您正在显示对话框或执行其他类似操作,我可以多次调用。