我需要类似网格布局的东西,但有自己的元素定位逻辑。我扩展了Frame Layout,并编写了以下逻辑:
super.onMeasure(widthMeasureSpec,heightMeasureSpec);
int childCount = getChildCount();
if (childCount==0) return;
int cellSize= 0;
for (int i=0;i<getChildCount();i++) {
cellSize = Math.max(cellSize, getChildAt(i).getMeasuredHeight());
}
cellSize= Math.min(getMeasuredHeight()/rowCount,cellSize);
if (autoColumnCount&&cellSize>0) {
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
Point displaySize = new Point();
display.getSize(displaySize);
int screenWidth = displaySize.x;
columnCount = Math.max(screenWidth/cellSize - autoColumnOffset,1);
}
cellSize = cellSize - cellPadding*2;
ArrayList<ArrayList<Integer>> sortedIndexes = new ArrayList<>();
int currentIndex=0;
while (true) {
if (currentIndex>=childCount) break;
ArrayList<Integer> indexes = new ArrayList<>();
indexes.add(currentIndex);
for (int y=1;y<rowCount;y++) {
int index = currentIndex + (y*columnCount);
if (index<childCount)
indexes.add(index);
else
break;
}
sortedIndexes.add(indexes);
currentIndex++;
if (currentIndex%columnCount==0) {
currentIndex = (currentIndex-columnCount)+(rowCount*columnCount);
}
}
int maxRows = 1;
for (int i=0;i<rowCount;i++) {
for (int y=0;y<sortedIndexes.size();y++) {
ArrayList<Integer> indexes = sortedIndexes.get(y);
if (i<indexes.size()) {
maxRows = Math.max(maxRows,i+1);
View v = getChildAt(indexes.get(i));
int newX = y*cellSize+(y+1)*cellPadding+y*cellPadding;
int newY = i*cellSize+(i+1)*cellPadding+i*cellPadding;
int measureSpecWidth = MeasureSpec.makeMeasureSpec(Math.min(cellSize,v.getMeasuredWidth()), MeasureSpec.AT_MOST);
int measureSpecHeight = MeasureSpec.makeMeasureSpec(Math.min(cellSize,v.getMeasuredHeight()), MeasureSpec.AT_MOST);
v.measure(measureSpecWidth, measureSpecHeight);
centerViewInBounds(v, newX, newY, newX + cellSize, newY + cellSize);
}
}
}
final int neededHeight = maxRows*cellSize+maxRows*cellPadding*2;
final int neededWidth = sortedIndexes.size()*cellSize+sortedIndexes.size()*cellPadding*2;
MyLog.print("asd", "Column count: " + sortedIndexes.size() + "\nCell size (with padding): " + (cellSize + cellPadding * 2) + "\nWidth: " + neededWidth);
setMeasuredDimension(neededWidth, neededHeight);
单元格应为方形,布局只能在宽度上增长并存储在HorizontalScrollView中。问题是函数setMeasuredDimension
工作不正确或我收到的大小是错误的(虽然,在我看来,一切都应该工作正常):有了这个逻辑我接下来的事情:
问题出在哪里?提前谢谢。
答案 0 :(得分:0)
好的,我读了所有关于&#34; android如何绘制视图&#34;在互联网上找到了更多的解释,我写了下一个逻辑:
private void sortChildren() {
int childCount = getChildCount();
sortedIndexes.clear();
int currentIndex=0;
while (true) {
if (currentIndex>=childCount) break;
ArrayList<Integer> indexes = new ArrayList<>();
indexes.add(currentIndex);
for (int y=1;y<rowCount;y++) {
int index = currentIndex + (y*columnCount);
if (index<childCount) {
indexes.add(index);
maxVisibleRows = Math.max(indexes.size(), maxVisibleRows);
} else break;
}
sortedIndexes.add(indexes);
currentIndex++;
if (currentIndex%columnCount==0) {
currentIndex = (currentIndex-columnCount)+(rowCount*columnCount);
}
}
maxVisibleColumns = sortedIndexes.size();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int width = 0;
int height = 0;
sortChildren();
switch (heightMode) {
case MeasureSpec.EXACTLY:
height = MeasureSpec.getSize(heightMeasureSpec);
cellSize = height/rowCount;
break;
case MeasureSpec.AT_MOST:
height = MeasureSpec.getSize(heightMeasureSpec);
cellSize = height/rowCount;
height = Math.min(height,cellSize* maxVisibleRows);
break;
case MeasureSpec.UNSPECIFIED:
cellSize = defaultCellSize;
height = defaultCellSize* maxVisibleRows;
break;
}
switch (widthMode) {
case MeasureSpec.EXACTLY:
width = MeasureSpec.getSize(widthMeasureSpec);
break;
case MeasureSpec.AT_MOST:
width = Math.min(MeasureSpec.getSize(widthMeasureSpec),maxVisibleColumns*cellSize);
break;
case MeasureSpec.UNSPECIFIED:
width = maxVisibleColumns*cellSize;
break;
}
int childCount = getChildCount();
for (int i=0;i<childCount;i++) {
View view = getChildAt(i);
int cellMeasureSpec = MeasureSpec.makeMeasureSpec(cellSize-cellPadding*2,MeasureSpec.EXACTLY);
view.measure(cellMeasureSpec,cellMeasureSpec);
}
setMeasuredDimension(width,height);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
for (int i=0;i<rowCount;i++) {
for (int y = 0; y < sortedIndexes.size(); y++) {
ArrayList<Integer> indexes = sortedIndexes.get(y);
if (i < indexes.size()) {
maxVisibleRows = Math.max(maxVisibleRows, i + 1);
View v = getChildAt(indexes.get(i));
if (v == null) continue;
int yOffset = (int)((1.0f*rowCount-maxVisibleRows)/2*cellSize);
int newX = y * cellSize;
int newY = i * cellSize + yOffset;
v.layout(newX + cellPadding, newY + cellPadding, newX + cellSize - cellPadding, newY + cellSize - cellPadding);
}
}
}
}
现在它按预期工作。