android - 在 ListView 中控制单行

标签 android android-listview android-animation android-adapter

我正在尝试向我的 ListView 添加一个动画,这样当来自 HTTP GET 请求的结果出现时,文本将淡入单独的行中。我知道如何实现淡入淡出效果,并且我已经有一个自定义 ListView 适配器,但问题是 ListView 每次出现结果时都会更新所有行,因此每次都会触发整个列表的淡入淡出效果。

我怎样才能控制单行,这样 ListView 就不会在每次数据更改时为每一行设置动画?

这是我用来填充 ListView 的代码:

    private class CustomAdapter extends ArrayAdapter<Row> {

    public CustomAdapter() {
        super(Results.this, R.layout.row, dataList);
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;
        RowHolder holder = null;
        if (row == null) {
            LayoutInflater inflater = getLayoutInflater();

            row = inflater.inflate(R.layout.row, parent, false);
            holder = new RowHolder(row);
            row.setTag(holder);
        } else {
            holder = (RowHolder) row.getTag();
        }
        try {
            holder.populateRow(dataList.get(position));
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
        return row;
    }

}

    private class RowHolder {
        private TextView label = null;
        private TextView count = null;
        private TextView result = null;

        public RowHolder(View row) {
            label = (TextView) row.findViewById(R.id.list_label);
            count = (TextView) row.findViewById(R.id.list_count);
            result = (TextView) row.findViewById(R.id.list_result);
        }

        public void populateRow(Row r) {
            label.setText(r.getLabel());
            count.setText(r.getCount());
            result.setText(r.getResult());
            label.startAnimation(fadeIn);
            count.startAnimation(fadeIn);
            result.startAnimation(fadeIn);
        }
    }

感谢任何帮助,提前致谢!

编辑 1:

我的异步任务:

    private class CheckSource extends AsyncTask<String, Void, String> {

    protected void onPreExecute() {
        results.setUnixTime(getUnixTime());
        results.setLabel(getString(R.string.label));
        results.setCount(null);
        results.setResult(null);
        results.setResultLabel("");
        results.setShowProgress(true);
        results.setIconType(null);
        results.setShowIcon(false);
        results.setHasResults(false);
        adapter.notifyDataSetChanged();
    }

    @Override
    protected String doInBackground(String... params) {

        String query = params[0];
        String httpResults = null;

        try {
            httpResults = getResults(query, "source");
            jsonObject = new JSONObject(httpResults);
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        return httpResults;
    }

    protected void onPostExecute(String results) {
        try {
            parseJSON(results);
        } catch (JSONException e) {
            e.printStackTrace();
            results.setResultLabel("<br />"
                    + getString(R.string.source_not_available) + "<br />");
        }
        results.setShowProgress(false);
        adapter.notifyDataSetChanged();
    }

    // Parse the retrieved json results
    private void parseJSON(String jsonResults) throws JSONException {
        if (jsonResults == null) {
            results.setResult(null);
            results.setHasResults(false);
            results.setResultLabel("<br />"
                    + getString(R.string.source_not_available) + "<br />");
            return;
        }
        jsonObject = new JSONObject(jsonResults);
        String result = null;
        String resultLabel = null;
        switch (jsonObject.getInt("count")) {
        case -1:
            results.setCount(null);
            results.setHasResults(false);
            resultLabel = getString(R.string.no_results);
            break;
        case 0:
            results.setCount(null);
            results.setHasResults(false);
            resultLabel = getString(R.string.no_results);
            break;
        case 1:
            results.setHasResults(true);
            results.setCount(jsonObject.get("count").toString() + " "
                    + getString(R.string.one_result));
            result = jsonObject.get("url").toString();
            resultLabel = getString(R.string.hyperlink_text);
            break;
        default:
            results.setHasResults(true);
            results.setCount(jsonObject.get("count").toString() + " "
                    + getString(R.string.multiple_results));
            result = jsonObject.get("url").toString();
            resultLabel = getString(R.string.hyperlink_text);
            break;
        }
        results.setResult(result);
        results.setResultLabel("<br />" + resultLabel + "<br />");
    }
}

执行HTTP请求的方法:

private String getResults(String query, String source)
        throws IllegalStateException, IOException, URISyntaxException {

    /* Method variables */
    StringBuilder builder = new StringBuilder();
    String URL = "url";
    URI uri;
    String phrase = "phrase";
    List<NameValuePair> params = new ArrayList<NameValuePair>();

    /* HTTP variables */
    HttpGet httpGet;
    DefaultHttpClient httpClient;
    HttpResponse httpResponse;
    HttpEntity httpEntity;
    HttpParams httpParams;

    int socketTimeout = 10000;
    int connectionTimeout = 10000;

    // Set the socket and connection timeout values
    httpParams = new BasicHttpParams();
    HttpConnectionParams
            .setConnectionTimeout(httpParams, connectionTimeout);
    HttpConnectionParams.setSoTimeout(httpParams, socketTimeout);
    httpClient = new DefaultHttpClient(httpParams);
    // Add parameters to the GET request
    params.add(new BasicNameValuePair("query", query));
    params.add(new BasicNameValuePair("type", source));
    String paramString = URLEncodedUtils.format(params, "utf-8");
    uri = new URI(URL + paramString);
    httpGet = new HttpGet(uri);
    // Execute the GET request
    httpResponse = httpClient.execute(httpGet);

    /* Read http response if http status = 200 */
    if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
        httpEntity = httpResponse.getEntity();
        InputStream content = httpEntity.getContent();
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                content));
        String line;
        while ((line = reader.readLine()) != null) {
            builder.append(line);
        }
    }
    return builder.toString();
}

最佳答案

正如 Romain Guy 不久前在 Google I/O session 期间解释的那样,仅更新 ListView 中的一个 View 的最有效方法如下所示(这个更新整个 View 数据):

ListView list = getListView();
int start = list.getFirstVisiblePosition();
for(int i=start, j=list.getLastVisiblePosition();i<=j;i++)
    if(target==list.getItemAtPosition(i)){
        View view = list.getChildAt(i-start);
        list.getAdapter().getView(i, view, list);
        break;
    }

假设 target 是适配器的一项。

此代码检索ListView,然后浏览当前显示的 View ,将您要查找的目标项与每个显示的 View 项进行比较,如果您的目标在其中那些,获取封闭 View 并在该 View 上执行适配器 getView 以刷新显示。

作为旁注,invalidate 并不像某些人期望的那样工作,也不会像 getView 那样刷新 View ,notifyDataSetChanged 将重建整个列表并最终调用getview 每个显示的项目和 invalidateViews 也会影响一堆。

最后一件事,如果他只需要更改行 View 的 subview 而不是像 getView 那样更改整行,那么他也可以获得额外的性能。在这种情况下,以下代码可以替换 list.getAdapter().getView(i, view, list);(更改 TextView 文本的示例):

((TextView)view.findViewById(R.id.myid)).setText("some new text");

在我们信任的代码中。

关于android - 在 ListView 中控制单行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9761869/

相关文章:

android ListView 不会突出显示选定的行

android - 更改表后 ListView 不工作。安卓

Android - 翻译 View 后仍保留空白

android - 使用动画android旋转图像位图

Android-MPChartLibrary “No Chart data available” 文字大小

android - FragmentActivity 操作栏选项菜单

android - 如何访问 sdcard 中所有子文件夹中的所有 mp3 文件?

Android - 只有最后一项显示在图层列表中

java - 使用 BaseAdapter 在 ListView 中显示 ArrayList

具有支持的 v4 jar 文件的 fragment 之间的 Android 翻转动画