android - ListView仅在自定义布局中滚动后显示更新的项目

时间:2015-01-13 22:25:00

标签: android android-layout listview

我需要一个布局,我可以在其中设置父级百分比的位置和大小,所以我创建了一个接受4个参数的自定义布局:

<declare-styleable name="MeshLayout_LayoutParams">
    <attr name="layout_xLocation" format="float"/>
    <attr name="layout_yLocation" format="float"/>
    <attr name="layout_xSize" format="float"/>
    <attr name="layout_ySize" format="float"/>
</declare-styleable>

每个参数可以设置在0到100之间。 布局代码:

public class MeshLayout extends ViewGroup {
    private float xSize;    //width of parent
    private float ySize;    //height of parent

    public MeshLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        //get size of parent
        xSize = getMeasuredWidth() / 100.0f;
        ySize = getMeasuredHeight() / 100.0f;

        for (int i = 0; i < getChildCount(); i++) {
            //calc size of child as percentage of parent's
            final View child = getChildAt(i);
            final LayoutParams childLP = (LayoutParams) child.getLayoutParams();
            final int childLeft = Math.round(childLP.xLocation * xSize);
            final int childTop = Math.round(childLP.yLocation * ySize);
            final int childWidth = Math.round((childLP.xLocation + childLP.xSize) * xSize) - childLeft;
            final int childHeight = Math.round((childLP.yLocation + childLP.ySize) * ySize) - childTop;

            child.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
                    MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY));
        }
    }

    @Override
    protected void onLayout(boolean b, int i, int i2, int i3, int i4) {
        if (b) {
            for (int childIdx = 0; childIdx < getChildCount(); childIdx++) {
                final View child = getChildAt(childIdx);
                final LayoutParams childLP = (LayoutParams) child.getLayoutParams();
                final int childLeft = Math.round(childLP.xLocation * xSize);
                final int childTop = Math.round(childLP.yLocation * ySize);

                child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(), childTop + child.getMeasuredHeight());
            }
        }
    }

    //FROM HERE ON IT'S ONLY LAYOUT PARAMETER STUFF...
    @Override
    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
        return p instanceof LayoutParams;
    }

    @Override
    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new LayoutParams(getContext(), attrs);
    }

    @Override
    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
        return new LayoutParams(p);
    }

    @Override
    protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(0, 0);
    }

    public class LayoutParams extends ViewGroup.LayoutParams {
        public float xLocation;
        public float yLocation;
        public float xSize;
        public float ySize;

        public LayoutParams(Context c, AttributeSet attrs) {
            super(0, 0);

            TypedArray array = c.obtainStyledAttributes(attrs, R.styleable.MeshLayout_LayoutParams);
            xLocation = limitLocation(array.getFloat(R.styleable.MeshLayout_LayoutParams_layout_xLocation, 0));  //default=0
            yLocation = limitLocation(array.getFloat(R.styleable.MeshLayout_LayoutParams_layout_yLocation, 0));  //default=0
            xSize = limitSize(xLocation, array.getFloat(R.styleable.MeshLayout_LayoutParams_layout_xSize, 100));  //default=100
            ySize = limitSize(yLocation, array.getFloat(R.styleable.MeshLayout_LayoutParams_layout_ySize, 100));  //default=100
        }

        public LayoutParams(int width, int height) {
            super(0, 0);
        }

        public LayoutParams(ViewGroup.LayoutParams source) {
            super(source);
        }

        private float limitLocation(float location) {
            return Math.min(Math.max(location, 0), 100);
        }

        private float limitSize(float location, float size) {
            return Math.max(Math.min(size, 100 - location), 0);
        }
    }
}

它在XML文件中的使用:

<picki_pic.com.cursortext.MeshLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:mesh="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <ListView android:id="@+id/myList"
        mesh:layout_ySize="90"/>

    <Button
        mesh:layout_yLocation="90"
        android:onClick="go"
        android:text="GO!"/>
</picki_pic.com.cursortext.MeshLayout>

我遇到的问题是当我用新值更新myList时,在向任何方向滚动它之前我无法看到它们。这是测试代码(使用SimpleCursorAdapter):

public class MainActivity extends ActionBarActivity {
    private SQLiteDatabase mMyDatabase;
    CursorAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //create database
        mMyDatabase = openOrCreateDatabase("DB", MODE_PRIVATE, null);
        mMyDatabase.execSQL("DROP TABLE IF EXISTS MyTable");
        mMyDatabase.execSQL("CREATE TABLE MyTable (_id INTEGER PRIMARY KEY)");
        mMyDatabase.execSQL("INSERT INTO MyTable VALUES(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11)");

        //set list's adapter (with a null cursor)
        final ListView myList = (ListView)findViewById(R.id.myList);
        mAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, null, new String[] {"_id"},
                new int[] {android.R.id.text1}, 0);
        myList.setAdapter(mAdapter);
    }

    public void go(View view) {
        //change the cursor to update the list
        mAdapter.changeCursor(mMyDatabase.query("MyTable", null, null, null, null, null, null));
    }
}

当我将MeshLayout更改为LinearLayout时,列表会正确显示更新的项目。

我已经尝试过调用notifyDataSetChanged(),使列表视图无效,滚动列表(使用scrollBy)以及我在网上找到的任何其他内容。我还搜索了我可能错过实施MeshLayout的任何内容,但找不到任何内容。

有没有人知道可能导致这种情况的原因?

谢谢!

0 个答案:

没有答案