我需要一个布局,我可以在其中设置父级百分比的位置和大小,所以我创建了一个接受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
的任何内容,但找不到任何内容。
有没有人知道可能导致这种情况的原因?
谢谢!