【问题标题】:ListView automatically moving to top when I scroll滚动时 ListView 自动移到顶部
【发布时间】:2013-11-07 10:44:05
【问题描述】:

我正在研究 TCP socketListView,它们有 20 个列表项。 我每 5 秒从服务器收到一组数据,我需要在 listview 中显示这些数据。

我的问题是。

当我滚动我的列表并从服务器收到第二组数据时,我需要更新我的列表项,然后我的listview 自动移动到顶部。我需要阻止它。

我的代码正在更新我的列表视图。此代码在 AsyncTask 的 onPostExecute 中。

protected void onPostExecute(ArrayList<User> result) {
    adb = new ArrayAdapter<User>(DefaultMarketWatch.this, R.layout.rssitemview, result) {
        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            View view = convertView;
            try {
                if (null == view) {
                    LayoutInflater vi = (LayoutInflater) DefaultMarketWatch.this
                            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    view = vi.inflate(R.layout.rssitemview, null);
                }
                final User u = list.get(position);
                if (null != u) {
                    TextView title = (TextView) view.findViewById(R.id.symbol);
                    TextView ltp = (TextView) view.findViewById(R.id.ltp);
                    TextView high = (TextView) view.findViewById(R.id.high);
                    TextView low = (TextView) view.findViewById(R.id.low);
                    TextView persendBold = (TextView) view.findViewById(R.id.persent_bold);

                    persendBold.setText(u.getAskPrice());
                    ltp.setText(u.getLtp());
                    title.setText(u.getSymbol());
                    high.setText(u.getHigh());
                    low.setText(u.getLow());
                } 
            }
            catch (Exception e) {
                e.printStackTrace();
            }
            return view;
        }

    };

    if (adb != null) {
        lv.setAdapter(adb);
        adb.notifyDataSetChanged();
        int currentPos = lv.getFirstVisiblePosition();
        lv.setSelection(currentPos);
    }
    super.onPostExecute(result);
}

【问题讨论】:

  • 发布代码如何更新列表视图..
  • 发生这种情况是因为每 5 秒更新一次列表......这会重置滚动位置。发布您的代码,以便我们为您提供解决方案..
  • 您是否在代码中使用了 setSelection?
  • 我已经更新了我的代码。请看。我用 setSelection() 没用。

标签: android listview android-listview timer android-asynctask


【解决方案1】:

问题是:你喜欢什么行为?如果列表项完全改变,显示第一个元素是合理的。但是,如果您只希望新数据的位置与以前相同,则可以执行以下操作:

protected void onPostExecute(ArrayList<User> result) {
    int currentPos = lv.getFirstVisiblePosition();
    adb = new ArrayAdapter<User>(DefaultMarketWatch.this, R.layout.rssitemview, result) {
        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            View view = convertView;
            try {
                if (null == view) {
                    LayoutInflater vi = (LayoutInflater) DefaultMarketWatch.this
                            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    view = vi.inflate(R.layout.rssitemview, null);
                }
                final User u = list.get(position);
                if (null != u) {
                    TextView title = (TextView) view.findViewById(R.id.symbol);
                    TextView ltp = (TextView) view.findViewById(R.id.ltp);
                    TextView high = (TextView) view.findViewById(R.id.high);
                    TextView low = (TextView) view.findViewById(R.id.low);
                    TextView persendBold = (TextView) view.findViewById(R.id.persent_bold);

                    persendBold.setText(u.getAskPrice());
                    ltp.setText(u.getLtp());
                    title.setText(u.getSymbol());
                    high.setText(u.getHigh());
                    low.setText(u.getLow());
                } 
            }
            catch (Exception e) {
                e.printStackTrace();
            }
            return view;
        }

    };

     //previous null check completely unnessesary, because you initialized it just before
    lv.setAdapter(adb);
    adb.notifyDataSetChanged();

    lv.setSelection(currentPos);

    super.onPostExecute(result);
}

【讨论】:

  • 请看我的代码我已经更新了。我使用了 setSelection() 但没有用。
  • @user2085965 你调用lv.getFirstVisibleItem()太晚了(在你为它设置了一个新的适配器之后)。试试我更新的代码,它应该可以工作,如果 lv 被初始化(看不到你的代码 lv 来自哪里)
  • @user2085965 “没有工作”不是一个好的回应。 1. 什么没有奏效。 2. 你期待什么? 3. 会发生什么? 4. 有错误吗? 5.您是否验证了您的数据? 6.你登录了吗,lv.getFirstVisibleItem()的结果(如果有,请发帖,如果没有,就做)!不要指望 SO 成员完全解决您的问题。我们只能根据给定的信息尝试提供帮助。您需要尽可能详细地向我们提供它们。只是提醒未来的问题:您提供的信息越多,就越有可能有人可以帮助您
【解决方案2】:

我认为问题在于您每次都为您的listView 设置了一个新的adapter。我的解决方案是实现一个自定义数组适配器,它在运行时支持update 列表..

步骤 1) 定义一个自定义 ArrayAdapter 如下:

public class MyArrayAdapter extends ArrayAdapter<User>
{
    ArrayList<User> list;

    public MyArrayAdapter (Context context, int textViewResourceId, ArrayList<User> result) {
       super (context, textViewResourceId, objects);
       this.list = result;
    }

    public void updateList(ArrayList<User> updatedList) {
        this.list = updatedList;
    }

    @Override
    public View getView (int position, View convertView, ViewGroup parent)
    {
        View view = convertView;
        try {
            if (null == view) {
                LayoutInflater vi = (LayoutInflater) DefaultMarketWatch.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                view = vi.inflate(R.layout.rssitemview, null);
            }
            final User u = list.get(position);
            if (null != u) {
                TextView title = (TextView) view.findViewById(R.id.symbol);
                TextView ltp = (TextView) view.findViewById(R.id.ltp);
                TextView high = (TextView) view.findViewById(R.id.high);
                TextView low = (TextView) view.findViewById(R.id.low);
                TextView persendBold = (TextView) view.findViewById(R.id.persent_bold);

                persendBold.setText(u.getAskPrice());
                ltp.setText(u.getLtp());
                title.setText(u.getSymbol());
                high.setText(u.getHigh());
                low.setText(u.getLow());
            } 
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return view;
    }
}

按如下方式初始化adb(在onCreate 或在启动AsyncTask 之前的任何地方:

adb = new MyArrayAdapter(DefaultMarketWatch.this, R.layout.rssitemview, new ArrayList<User>());
lv.setAdapter(adb);
adb.notifyDataSetChanged();

您的帖子执行现在只会告诉适配器列表已更新,并调用通知数据集已更改。

protected void onPostExecute(ArrayList<User> result) {
    adb.updateList(result);
    adb.notifyDataSetChanged();
    super.onPostExecute(result);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-14
    相关资源
    最近更新 更多