【问题标题】:Can't scroll ListView properly无法正确滚动 ListView
【发布时间】:2014-06-01 04:28:17
【问题描述】:

我在一个片段中有一个 ListView,其中包含从网上下载的数据。我将数据保存在缓存中,以便在对服务器的请求完成之前显示信息。

问题是当我向下滚动列表视图时开始向下滚动,几秒钟后它会自动转到顶部,所以我无法选择列表底部的元素,因为我没有时间。

listView的布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:orientation="vertical">

    <ProgressBar
         android:id="@+id/progressbar_line"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         style="?android:attr/progressBarStyleHorizontal"
         android:indeterminate="true"/>

    <ListView
        android:id="@+id/list_stop"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:layout_weight="1"
        android:choiceMode="singleChoice"
        android:visibility="invisible"
        android:divider="@color/divider_color"
        android:dividerHeight="1dp" />

</LinearLayout>

使用listView的片段

public class LineFragment extends Fragment implements RestoreActionBar {

    private static final String ARG_LINE_NAME = "line_name";
    private static final String ARG_LINE_COLOR = "line_color";

    /**
     * A pointer to the current callbacks instance (the Activity).
     */
    private LineFragmentCallbacks mCallbacks;

    private Line mLine;

    private ProgressBar mProgressBar;
    private ListView mListView;

    private DownloadToCache mDownloadToCacheAsyncTask = null;

    /**
     * Returns a new instance of this fragment for the given line
     * name.
     */
    public static LineFragment newInstance(String lineName, String lineColor) {
        LineFragment fragment = new LineFragment();
        Bundle args = new Bundle();
        args.putString(ARG_LINE_NAME, lineName);
        args.putString(ARG_LINE_COLOR, lineColor);
        fragment.setArguments(args);
        return fragment;
    }

    public LineFragment() {
        mLine = null;
    };

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mDownloadToCacheAsyncTask != null)
            mDownloadToCacheAsyncTask.cancel(true);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (mDownloadToCacheAsyncTask != null)
            mDownloadToCacheAsyncTask.cancel(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_line, container, false);
        mProgressBar = (ProgressBar) rootView.findViewById(R.id.progressbar_line);
        mListView = (ListView) rootView.findViewById(R.id.list_stop);
        mListView.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                selectItem(position);
            }          
        });

        setUpContentListStop(false);

        return rootView;
    }

    private void selectItem(int position) {
        if (mListView != null) {
            mListView.setItemChecked(position, true);
        }
        if (mCallbacks != null) {
            mCallbacks.onLineFragmentItemSelected(position);
        }
   }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        mCallbacks = (LineFragmentCallbacks) activity;

        File jsonFile = new File(activity.getCacheDir() 
                + getArguments().getString(ARG_LINE_NAME) 
                + ".json");
        if (jsonFile.exists()) {
                mLine = new Line(jsonFile);
        }

        ((MainActivity) activity).onSectionAttached(
                getArguments().getString(ARG_LINE_NAME),
                getArguments().getString(ARG_LINE_COLOR));
        ((MainActivity) activity).restoreActionBar();
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mCallbacks = null;
    }

    @Override
    public void restoreActionBar(Activity activity) {
        if (mListView != null) {
            mListView.setItemChecked(mListView.getCheckedItemPosition(), false);
        }
        ((MainActivity) activity).setActionBarProperty(
                getArguments().getString(ARG_LINE_NAME),
                Color.parseColor(getArguments().getString(ARG_LINE_COLOR)));
    }

    private void onFileInCacheChanged() {
        setUpContentListStop(true);
    }

    /**
     * Set up the content of the list
     * @param downloaded true if the json has been download
     */
    private void setUpContentListStop(boolean downloaded) {
        if (getActivity() == null)
            return;

        if (Network.isConnected(getActivity())) {
            mDownloadToCacheAsyncTask = new DownloadToCache();
            mDownloadToCacheAsyncTask.execute(
                        getArguments().getString(ARG_LINE_NAME) + ".json",
                        Line.URL_LINE_INFO);
        }

        File jsonFile = new File(getActivity().getCacheDir() + "/"
                + getArguments().getString(ARG_LINE_NAME) 
                + ".json");
        if (jsonFile.exists()) {
                mLine = new Line(jsonFile);
                return;
            }        

        mListView.setAdapter(new StopListAdapter(getActivity(), mLine.getListStops()));
        mListView.setVisibility(View.VISIBLE);
        } 
    }

    /* -------------AsyncTask class------------ */
    private class DownloadToCache extends AsyncTask<String, Void, Boolean> {

    }

    /**
     * Callbacks interface that all activities using this fragment must implement.
     */
    public static interface LineFragmentCallbacks {
        /**
         * Called when an item in the list is selected.
         */
        void onLineFragmentItemSelected(int position);
    }

}

【问题讨论】:

    标签: android listview android-fragments android-listview


    【解决方案1】:

    据我所知,每次缓存中的文件发生更改时,您都会调用setUpContentListStop (onFileInCacheChanged)。

    setUpContentListStop 方法中,您每次都在创建和设置列表视图的适配器:mListView.setAdapter(new StopListAdapter(getActivity(), mLine.getListStops()));。相反,您可以创建一次适配器(在onCreateView 中),并在新数据可用时更新其数据。

    编辑

    如果您的StopListAdapter 扩展了BaseAdapter,您可以创建一个额外的方法来在您的对象列表中添加一个新项目。

    public void add(Object item) {
       list.add(item);
       notifyDataSetChanged();
    }
    

    并在您的 setUpContentListStop 方法中调用此方法,例如 adapter.add(mLine.getListStops()))

    【讨论】:

    • 是的,你明白了,但是我如何更新适配器中的数据?
    • StopListAdapter是什么适配器?
    • 它扩展了BaseAdapter
    • 您可以添加一个add 方法,在该方法中您将一个附加项添加到您的内部对象List,然后通过调用notifyDataSetChanged() 通知数据已更改。
    • 是的,我找到了。谢谢,这就是问题所在。
    猜你喜欢
    • 2019-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-20
    • 1970-01-01
    相关资源
    最近更新 更多