使用 GridView 居中方形棋盘

Centered square chessboard using GridView

似乎这个问题已经被问过很多次了,我已经阅读了很多问题和他们的答案,但其中 none 适合我的问题:

我的情况:

我看到了两种可能的解决方案来处理这个问题,但我无法让它们工作:

  1. 为了得到一个漂亮的方形棋盘,我使用了下面的xml:

    <GridView
        android:id="@+id/chessboard_gridview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="2dp"
        android:layout_margin="10dp"
        android:background="@color/black"
        android:layout_gravity="center"
        android:gravity="center" >
    </GridView>
    

    onCreate() 我的 activity 中的以下代码:

    gridView.setNumColumns(board.getColumns());
    gridView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener(){
    
        @Override
        public void onGlobalLayout() {
    
            int size = Math.min(gridView.getWidth(), gridView.getHeight());
    
            ViewGroup.LayoutParams params = gridView.getLayoutParams();
            params.width = size;
            params.height = size;
            gridView.setLayoutParams(params);
    
            gridView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }});
    

    为了得到完美的正方形,我找到了我的自定义适配器使用的 ImageView 的以下解决方案:

    public class SquareView extends ImageView{
    
        public SquareView(Context context){
            super(context);
        }
    
        @Override
        public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, widthMeasureSpec);
        }
    }
    

    但是,如果我看一下结果,我会发现边界线的粗细不同,因为棋盘不能被列数整除:

    如果我以某种方式设法使所有方块都在 GridView 中居中,我可以接受。然后border比2dp还粗,有可能一侧比另一侧厚一个像素,不过我不在乎

    问题:我怎样才能使方块居中以使边框厚度不会随延伸变化而变化?

  2. 另一种方法是有一个正好为 2 dp 的漂亮边框,但正方形并不是真正的正方形。剩余的 space 使右侧和底部的边框变粗,可以或多或少均匀地分布在正方形上。例如:如果还有 3 个剩余像素,则使第 2、4、6 列各宽一个像素,使第 2、4、6 行高一个像素。

    问题:如何才能将所有 GridView space 完美地用于我的正方形,即使这意味着我的正方形不再是真正的正方形,但有些稍宽或稍高?

    我原以为 GridView 会自动拉伸它们,但如果我使用简单的 ImageView 而不是我的 SquareView 作为方块,如果我不自己设置每个方块的大小,我就会得到一个黑色的棋盘。如果我手动为正方形设置正方形大小,我会得到所有 stretchModes 的不同错误结果。

希望我没看错你的问题。问题可能是由于大小不能被 board.getColumns 整除。所以我们可以选择一个 newSize,它对于给定的板列来说是可等分的。

gridView.setNumColumns(board.getColumns());
gridView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener(){
@Override
public void onGlobalLayout() {
    int size = Math.min(gridView.getWidth(), gridView.getHeight());
    int newsize = (size/board.getColumns()) * board.getColumns(); // computing new size

    ViewGroup.LayoutParams params = gridView.getLayoutParams();
    params.width = newsize; //assigning new size
    params.height = newsize; //assigning new size
    gridView.setLayoutParams(params);

    gridView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}});

我很久以前就问过这个问题,然后决定写下我是如何解决我的问题的。最后,我不在乎更改行数和列数时棋盘大小可能会有所不同。请注意,可能会有更新的答案。这是一个在 2015 年对我有用的解决方案。

我的网格视图:

<GridView
    android:id="@+id/chessboard_gridview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:background="@color/black"
    android:gravity="center"
    android:padding="2dp">
</GridView>

在 Activity 的 onCreate 中初始化:

this.gridView = (GridView) findViewById(R.id.chessboard_gridview);

相同的 Activity 为棋盘使用自定义适配器:

ChessboardViewAdapter adapter = new ChessboardViewAdapter(numRows, numCols, ...);       
gridView.setAdapter(adapter);

ChessboardViewAdapter 然后(除其他事项外)确定正方形的适当大小。请注意,SquareView 是一个自定义 class,它不再像我最初问题中的代码那样覆盖 onMeasure

public class ChessboardViewAdapter extends BaseAdapter{
    ...
    @Override
    public View getView(int position, View convertView, ViewGroup parent){

        View view = convertView;
        if(view == null){
            view = new SquareView(context);
        }

        // Adjust each square's size to look like a square
        int parentPadding = 2 * parent.getPaddingTop(); // equal paddings
        int newSize = (parent.getWidth() - parentPadding) / this.columns;
        view.setLayoutParams(new GridView.LayoutParams(newSize, newSize));
        view.setPadding(10, 10, 10, 10); // hard coded offsets for the black border
        ...
    }
}