1

我有一个扩展ListView的自定义。该列表是在这样的布局中定义的:AdapterCursorAdapter

<RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center">

        <ProgressBar
            android:id="@android:id/empty"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            style="@style/ProgressBar.Itasa.Indeterminate.Large"/>

    <net.italiansubs.droitasa.widget.HookedListView
            android:id="@android:id/list"
            style="@style/NewsList"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="gone"/>

</RelativeLayout>

HookedListView看起来像这样:

package net.italiansubs.droitasa.widget;

import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.widget.ListView;
import net.italiansubs.droitasa.util.OnLayoutChangedListener;

/**
 * An extended ListView that has an hook for getting layout changes.
 *
 * @author Sebastiano Poggi, Francesco Pontillo
 */
public class HookedListView extends ListView {

    private OnLayoutChangedListener mLayoutListener;
    private final Handler mHandler;
    private boolean mFirstLayout = true;

    public HookedListView(Context context) {
        super(context);
        mHandler = new Handler(context.getMainLooper());
    }

    public HookedListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mHandler = new Handler(context.getMainLooper());
    }

    public HookedListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mHandler = new Handler(context.getMainLooper());
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);

        if (mFirstLayout) {
            // In this case we want to avoid posting, because this could
            // have the two layout passes happen one after the other with
            // a pause between each other, with the effects, for example,
            // of having the number of columns change
            mFirstLayout = false;

            new LayoutChangedRunnable().run();
        }
        else if (changed) {
            mHandler.postAtFrontOfQueue(new LayoutChangedRunnable());
        }
    }

    /**
     * Sets the OnLayoutChangedListener for this instance, that will
     * receive callbacks after layout changes for the View.
     *
     * @param l The new OnLayoutChangedListener, or null to remove
     *          the current listener.
     */
    public void setOnLayoutChangedListener(OnLayoutChangedListener l) {
        mLayoutListener = l;
    }

    /**
     * Gets the OnLayoutChangedListener set for this instance.
     *
     * @return Returns the instance's OnLayoutChangedListener, if any.
     */
    public OnLayoutChangedListener getOnLayoutChangedListener() {
        return mLayoutListener;
    }

    private class LayoutChangedRunnable implements Runnable {

        @Override
        public void run() {
            // We don't need to synchronize on the listener because the handler
            // is hooked up to the main thread's looper so we shouldn't be
            // called from other threads.

            if (mLayoutListener != null) {
                mLayoutListener.onLayoutChanged(HookedListView.this);
            }
        }
    }
}

我遇到的问题是ListView内容没有出现在设备上,即使Cursor有项目,Adapter有项目,ListView本身也有项目。将HierarchyViewer附加到窗口确实可以使ListView项目在没有任何进一步干预的情况下出现,并且请求从 web 服务更新数据也是如此,这反过来会更新ContentProvider. Cursor我已经尝试为和设置内容观察器Adapter,并记录以确保将正确数量的项目设置为Adapter,并且一切都按预期工作。由于我们的自定义,我们已经在 List 上执行了一轮额外的布局MultiCoumnAdapter,计算第一轮之后的列数ListView布局传递(因此需要 a HookedListView)。

我尝试过使用标准CursorAdapter,而不是我自己的MultiColumnAdapter(模拟 a GridView,没有所有限制和错误),但这并没有改变任何东西。

FragmentActivity;的唯一内容 本身基本上什么也不做,只是从用于启动它Activity的附加组件中获取项目 ID ,并将其传递给,它在的布局 XML 中定义为唯一的元素。IntentFragmentActivity

所做的Fragment只是处理ContentProvider使用标准从应用程序获取数据CursorLoader。我们使用DataDroid来管理从 web 服务获取新数据。

有没有人对这里发生的事情有丝毫线索?似乎有些东西卡在ListView自己的代码中,直到我们更新底层Cursor......

4

1 回答 1

5

您在 ListView 上搞乱 onLayout 的事实敲响了警钟。为什么不直接使用带有OnGlobalLayoutListener的标准 ListView呢?

或者,如果您需要自定义 ListView,请尝试将您的更改onLayout()为:

final LayoutChangedRunnable mLayoutRunnable = new LayoutChangedRunnable()

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    super.onLayout(changed, l, t, r, b);

    if (changed) {
        post(mLayoutRunnable);
    }
}
于 2013-04-15T11:56:23.907 回答