Android 使用GridView居中方形棋盘

Android 使用GridView居中方形棋盘,android,android-layout,gridview,border,Android,Android Layout,Gridview,Border,这似乎已经被问了很多次了,我读了很多问题和答案,但没有一个适合我的问题: 我的情况: 在我的活动中,在一堆其他东西下面,你应该看到一个棋盘。对于小/短智能手机,棋盘(正方形)的剩余空间可能不太大。因此,我不能简单地说棋盘的大小是由剩余的宽度决定的。如果剩余高度较低,则高度决定尺寸 游戏中的方块数各不相同。棋盘将始终为正方形,但其尺寸从3x3到8x8不等 我希望我的棋盘(通过使用GridView实现)有一个黑色边框(大约2pd) 如果棋盘上的方块可以是真正的方块就好了。但我希望棋盘的大小是固定的

这似乎已经被问了很多次了,我读了很多问题和答案,但没有一个适合我的问题:

我的情况:

  • 在我的活动中,在一堆其他东西下面,你应该看到一个棋盘。对于小/短智能手机,棋盘(正方形)的剩余空间可能不太大。因此,我不能简单地说棋盘的大小是由剩余的宽度决定的。如果剩余高度较低,则高度决定尺寸
  • 游戏中的方块数各不相同。棋盘将始终为正方形,但其尺寸从3x3到8x8不等
  • 我希望我的棋盘(通过使用GridView实现)有一个黑色边框(大约2pd)
  • 如果棋盘上的方块可以是真正的方块就好了。但我希望棋盘的大小是固定的,即使列的数量不同。因此,我不能有一个恒定的边界厚度和真正的正方形,因为棋盘的大小(减去边界厚度)不能保证能被列数整除
我认为有两种可能的解决方案可以解决这个问题,但我无法让它们发挥作用:

  • 为了获得一个漂亮的方形棋盘,我使用了以下xml:

    
    

    在我的活动中的
    onCreate()
    中输入以下代码:

    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中居中,那么我可以接受。然后边界比2dp厚,可能一边比另一边厚一个像素,但我不在乎

    问题:如何使正方形居中,使边界厚度不随延伸而变化

  • 另一种方法是有一个精确的2 dp的好边界,但正方形并不是真正的正方形。使右侧和底部边界更厚的剩余空间可以在正方形上或多或少均匀分布。例如:如果还有3个剩余像素,则使用2,4。六,。列每宽一个像素,2,4。六,。排高一点

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

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


  • 希望我读对了你的问题。问题可能是因为board.getColumns不能等分大小。因此,我们可以选择一个新闻大小,对于给定的board列,它可以被等分

    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>
    
    同一活动使用棋盘的自定义适配器:

    ChessboardViewAdapter adapter = new ChessboardViewAdapter(numRows, numCols, ...);       
    gridView.setAdapter(adapter);
    
    然后,
    棋盘视图适配器
    确定正方形的适当大小。请注意,
    SquareView
    是一个自定义类,它不再像我最初的问题中的代码那样覆盖
    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
            ...
        }
    }
    

    谢谢你的帮助,但我已经写过,我知道问题是由于大小不能被列数平均整除。我说我希望我的棋盘大小是固定的。然后分配padding=(size newsize)/2你能解决这个问题吗?我已经考虑过了,但我认为,动态更改padding可能会带来很多麻烦。如果我更改generell填充,这将无法修复任何问题;如果我分别更改顶部、底部等,并使用不同的值,我会把事情搞砸,因为我必须使用负填充。
    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
            ...
        }
    }