草庐IT

安卓六角网格

coder 2023-12-03 原文

我需要开发一个应用程序,其中的按钮是六边形的,并且所有按钮都彼此相邻放置,形成一个网格。鉴于我在 Android 方面的经验不足,我想知道 GridView 是否是最好的方法。如果是这样的话,我怎么能把六边形并排放置呢?

我现在有这个

在 main.xml 中使用此布局:

<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/gridview"
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"
    android:padding="0dp"
    android:verticalSpacing="0dp"
    android:horizontalSpacing="0dp"
    android:numColumns="4"
    android:columnWidth="0dp"
    android:stretchMode="columnWidth"
    android:gravity="top"
/>

这就是我想要得到的:

我需要一些帮助才能将六边形彼此连接成固定结构。我一直在玩弄布局值,但没有成功。 TableView 会是更好的方法吗? 非常感谢

最佳答案

这是我在一个应用程序中使用的一些代码(它叫做“Connect3,如果你想玩的话:))。它是一个自定义布局类,可以在网格中绘制六边形图像。网格可以是三角形或倾斜的矩形。

代码计算每个 imageview 的边界(以像素为单位,相对于 hexgrid 的原点),然后调用 imageView.layout(left,top,right,bottom) 来设置计算出的边界。计算并不难。主要参数是六边形的半径。由此,总高度、总宽度、有效高度和有效宽度( ImageView 的高度/宽度分别是两个连续 View 的上边界/左边界之间的距离)。然后归结为一些简单的 for 循环来绘制它们。

要使 View 可点击,只需在创建 View 时设置一个onClickListener。 (我将其设为类(class)成员,因为它使事情变得更容易)。

onMeasure 函数仅计算 View 的总宽度和高度,并使用这些值调用 setMeasuredDimension

用于所有这些的图像只是您在操作栏下方看到的单个六边形。请注意,图像是正方形。

    @Override
protected void onLayout(final boolean changed, final int l, final int t, final int r, final int b) {
    Log.d(TAG, "board.onlayout called with size "+mSize+" l: "+l+" r: "+r+" t: "+t+" b: "+b);

    //If the dimensions of the board haven't changed, a redraw isn't necessary. Just update the images of the views instead by calling invalidate().
    if (!changed && !mSizeInvalidated) {
        invalidate();
        return;
    }
    int childCount = getChildCount();

    //Calculate some useful parameters.
    float radius = getResources().getDimension(R.dimen.radius);
    float verticalMargin = -radius / 4;
    float horizontalMargin = ((float) Math.sqrt(3) / 2 - 1) * radius;
    float height = 2 * radius;
    float width = height;
    float effectiveHeight = height + 2 * verticalMargin;
    float effectiveWidth = width + 2 * horizontalMargin;

    float totalHeight=(radius * (3 * mSize + 1)) / 2;
    float totalWidth;
    switch (mGameType) {
        case Connect3Turn.GAME_TYPE_HEX:
            totalWidth = (((float) mSize * 3  - 1)/ 2) * ((float) Math.sqrt(3)) * radius;
            break;
        case Connect3Turn.GAME_TYPE_Y:
        default:
            totalWidth = mSize * ((float) Math.sqrt(3)) * radius;
    }

    LayoutParams layoutParams = new LayoutParams((int) width, (int) height);

    //Code to calculate the offsets for horizontal and vertical centering (this is an option in the .xml file)
    //The GAME_TYPE_HEX creates a tilted rectangular board and GAME_TYPE_Y creates a triangular board.
    float x_offset_row;
    switch (mGameType) {
        case Connect3Turn.GAME_TYPE_Y:
            x_offset_row=(mSize - 1) * effectiveWidth / 2 + horizontalMargin;
            break;
        case Connect3Turn.GAME_TYPE_HEX:
        default:
            x_offset_row=0;
    }
    switch (mCenterHorizontal) {
        //the left side of the grid should be at non-negative coordinates.
        case 1: {
            x_offset_row += Math.max(0,(r-l-totalWidth)/2);
            break;
        }
        case 2: {x_offset_row += Math.max(0,(r-l-totalWidth));
            break;
        }
        case 0:
        default: {
            break;
        }
    }

    //calculate the y_offset for vertical centering.
    float y_offset = 0;
    switch (mCenterVertical) {
        case 1: {
            y_offset = Math.max(0, (b - t - totalHeight) / 2);
            break;
        }
        case 2: {
            y_offset = Math.max(0, (b - t -totalHeight));
            break;
        }
    }


    int cell = 0;
    for (int row = 0; row < mSize; ++row) {
        float x_offset = x_offset_row;
        int rowLength;
        //The row length depends on the board-type we want to draw.
        switch (mGameType){
            case Connect3Turn.GAME_TYPE_HEX:
                rowLength=mSize;
                break;
            case Connect3Turn.GAME_TYPE_Y:
            default:
                rowLength=row+1;
        }
        Log.d(TAG, "Drawing row "+row+" with "+rowLength+" cells.");
        for (int col = 0; col < rowLength; ++col) {
            ImageView v;
            if (cell < childCount) {
                v = (ImageView) getChildAt(cell);
            } else {
                v = new ImageView(super.getContext());
                v.setLayoutParams(layoutParams);
                v.setOnClickListener(onClickListener);
                addViewInLayout(v, cell, v.getLayoutParams(), true);
            }

            //Set the image (color) of the cell and put its index in a tag, so we can retrieve the number of the clicked cell in the onClickListener.
            v.setImageResource(mImageIds[mImages[cell]]);
            v.setTag(cell);

            //Set the bounds of the image, which will automatically be cropped in the available space.
            v.layout((int) x_offset, (int) y_offset, (int) (x_offset + width), (int) (y_offset + height));
            x_offset += effectiveWidth;
            ++cell;
        }
        y_offset += effectiveHeight;
        //The offset of the next row, relative to this one, again depends on the game type.
        switch(mGameType){
            case Connect3Turn.GAME_TYPE_Y:
                x_offset_row -= effectiveWidth / 2;
                break;
            case Connect3Turn.GAME_TYPE_HEX:
                x_offset_row += effectiveWidth / 2;
        }
    }

    //We updated all views, so it is not invalidated anymore.
    mSizeInvalidated=false;
}

关于安卓六角网格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8840729/

有关安卓六角网格的更多相关文章

  1. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  2. ruby-on-rails - 你能为 Ruby on Rails 推荐好的数据网格类/gem 吗? - 2

    您能为RubyonRails推荐好的数据网格类/gem吗?喜欢http://code.google.com/p/zend-framework-datagrid/采埃孚 最佳答案 你也可以试试datagridgem。这不仅关注带有列的网格,还关注过滤器。classSimpleReportincludeDatagridscopedoUser.includes(:group)endfilter(:category,:enum,:select=>["first","second"])filter(:disabled,:eboolean)fi

  3. ruby-on-rails - 网格与Rails? - 2

    网格支撑排序数据。搜索全选/无轨道上有网格吗? 最佳答案 为铁路电网提供丰富的信息。请参阅此链接。http://www.2dconcept.com/jquery-grid-rails-plugin 关于ruby-on-rails-网格与Rails?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/5100498/

  4. (一)专题介绍:移动端安卓手机改造成linux服务器&linux服务器中安装软件、部署前后端分离项目实战 - 2

    快捷目录前言一、涉及到的相关技术简介二、具体实现过程及踩坑杂谈1.安卓手机改造成linux系统实现方案2.改造后的手机Linux中软件的安装3.手机Linux中安装MySQL5.7踩坑实录4.手机Linux中安装软件的正确方法三、Linux服务器部署前后端分离项目流程1.前提准备(安装必要软件,搭建环境):2.前后端分离项目的详细部署过程:总结前言总体概述:本篇文章隶属于“手机改造服务器部署前后端分离项目”系列专栏,该专栏将分多个板块,每个板块独立成篇来详细记录:手机(安卓)改造成个人服务器(Linux)、Linux中安装软件、配置开发环境、部署JAVA+VUE+MySQL5.7前后端分离项目

  5. 在所有移动屏幕尺寸上支持设计两个卡视图和瓷砖网格 - 2

    我需要设计下面的视图。解释:前两个视图是卡片视图。顶部将包含下面的图表是4个瓷砖,该图像在其底部具有图像和文本问题:我能够获得这样的设计,但并不适合所有手机和屏幕类型。我怎样才能解决这个问题?代码:看答案尝试这个:您需要使用线性布局并将重量分配给两个卡布局50-50。

  6. javascript - 除非调整浏览器窗口的大小,否则 Angular ui 网格不会显示内容 - 2

    我正在使用angularjs1.5.0和angularuigrid3.1.1。当我像这样在Controller主体中分配gridOptions(传递给grid指令)对象时:$scope.gridOptions={data:[{"mock2":1,"mock1":2},{"mock2":10,"mock1":22}]};HTML:它按预期显示表格。但是当我尝试更改$scope.on中的数据时:$scope.$on('update',function(event,passedFromBroadcast){$scope.gridOptions.data=[{"mock2":"set","mo

  7. javascript - Three.js 网格调整大小 - 2

    我有一个3D模型,它作为obj文件加载到Three.js中。模型本身就是一件家具。问题是,家具Material是动态的并且尺寸(厚度)不同。我需要能够使Material的厚度更大,但模型的总尺寸不能改变。所以缩放不是一种选择。有没有一种方法可以调整模型部分(少数特定网格)的大小并且不损害网格本身的结构?我需要改变结构的厚度,但模型的内部零件不应该改变。我能想到的唯一解决方案是更改一些网格的比例,然后基于此更改其他网格的全局位置。这是正确的方法吗?object.traverse(function(child){if(childinstanceofTHREE.Mesh){//resizea

  8. javascript - 在缩放/拖动时缩放/重绘 d3.js 网格线 - 2

    我昨天才开始使用d3.js,但在完成我的工作时遇到了一些麻烦。现在我创建了一个带有两个y轴的图表,每个显示一些值,x轴显示日期。点击y轴上的值,我会显示相应的水平网格线。我的问题是,在放大或缩小或拖动时,网格线(水平和垂直)无法根据轴值正确缩放,它们根本就不动。我今天下午进行了很多搜索,找到了一些如何执行此操作的示例,但它们似乎都不适用于我已有的代码。我想,应该将逻辑添加到缩放行为中,但我不确定//xaxisgridlinesfunctionmake_x_gridlines(){returnd3.axisBottom(x).ticks(5)}//addtheXgridlinesletx

  9. javascript - ExtJS 使网格高度为 100% - 2

    我在这里发现了2个类似的问题,但它们对我没有帮助,我的代码是:vargrid=Ext.create('Ext.grid.Panel',{autoScroll:true,//ifsetthistoanynumericvalue,theneverythingworksjustgood,but//iwashopingthat`ExtJS`alreadycandetectbrowserwindowheight,amiwrong?height:'100%',title:'Products',store:store,itemId:'product_grid',columns:[..columnss

  10. javascript - ExtJS:什么是检测网格数据更改的网格面板事件 - 2

    我有一个GridPanel,在工具栏中我有两个按钮“拒绝更改”和“保存更改”。下面的代码显示了每个按钮的作用,到目前为止一切正常。Ext.define('APP.view.MyGrid',{extend:'Ext.grid.Panel',...initComponent:function(){varme=this;me.store=myStore;me.plugins=[Ext.create('Ext.grid.plugin.CellEditing',{clicksToEdit:1,autoCancel:false}),];me.rejectBtn={xtype:'button',id

随机推荐