草庐IT

android - 带六边形触摸区域的六边形按钮

coder 2023-12-15 原文

我需要创建与下图相同的按钮。 Button 必须包含里面的文字。

  • >

当我制作XML 布局时,我遇到了Button 触摸区域的问题。每个下一个按钮都用一个矩形 Button 区域覆盖上一个按钮。

  • >

像我一样在 XML 标记中放置六边形是否正确,以实现图片中的六边形?请帮我解决触摸区域的问题,如果可能的话请告诉我如何正确创建布局,因为我不确定我做的是否正确。

这是我的测试布局的一部分:

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:layout_marginTop="?attr/actionBarSize">


            <Button
                android:id="@+id/button1"
                android:layout_width="130dp"
                android:layout_height="134dp"
                android:background="@drawable/hexagon_shape_img"
                android:text="Home page"
                android:textSize="@dimen/small_text" />

            <Button
                android:id="@+id/button2"
                android:layout_width="130dp"
                android:layout_height="134dp"
                android:layout_marginLeft="65dp"
                android:layout_marginTop="-20dp"
                android:background="@drawable/hexagon_shape_img"
                android:text="Tavern"
                android:textSize="@dimen/small_text" />

        </LinearLayout>

最佳答案

好吧,事实证明这比我想象的要复杂。基本问题是最高的 Z 顺序按钮总是获得触摸事件,但不会在较低的 Z 顺序上传递它,即使它不处理事件也是如此。要让两个按钮都看到事件,需要一个解决方法。这是基本方法:

1: 在 Fragment/Activity 中创建一个容器来存放你的十六进制按钮

2:创建一个 fragment ,其中包含按钮和位于所有按钮之上的另一个按钮,alpha = 0

3: 添加一个 getOverlay():View 方法返回那个 alpha=0 按钮

4: 在 fragment 中实现一个 hitTest():Button 方法

5:在主Activity/Fragment中,设置监听器来处理覆盖按钮的触摸事件

我制作(并测试)了一个应用程序来演示这个概念。我将把 hitTest 留给你,因为它相当乏味

activity_main.xml:

<RelativeLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" 
android:layout_width="match_parent"
android:layout_height="match_parent" 
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" 
tools:context=".MainActivity">

    <FrameLayout android:id="@+id/main_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>

fragment 按钮.xml:

<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.me.testapplication.Buttons">

    <Button android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/lorem"/>
    <Button android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/lorem_ipsum"
        android:alpha="0.4"/>
    <Button android:id="@+id/overlay"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:alpha="0"/>

</FrameLayout>

主要 Activity .java:

public class MainActivity extends ActionBarActivity {
    public static final String DEBUG_TAG = "TEST";

    private Buttons mButtons;
    private GestureDetector mGestureDetector;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mButtons = Buttons.newInstance();
        getFragmentManager().beginTransaction()
                .replace(R.id.main_container, mButtons)
                .commit();

        mGestureDetector = new GestureDetector(this, mGestureListener);
    }

    @Override
    protected void onStart() {
        super.onStart();

        View overlay = mButtons.getOverlay();
        if (overlay != null) {
            overlay.setOnTouchListener(mTouchListener);
        }
    }
    ...
    private View.OnTouchListener mTouchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
             return mGestureDetector.onTouchEvent(event);
        }
    };

    private GestureDetector.OnGestureListener mGestureListener
            =new GestureDetector.OnGestureListener()
    {
            @Override
            public boolean onDown(MotionEvent e) {
            String buttonHit = mButtons.hitTest(e);
            Log.i(DEBUG_TAG, buttonHit);
            return true;
        }
        ...
    };
}

按钮.java:

public class Buttons extends Fragment {

    Button mButton1, mButton2;
    View mOverlay;

    public static Buttons newInstance() {
        return new Buttons();
    }

    public Buttons() {}

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.fragment_buttons, container, false);
        mButton1 = (Button) root.findViewById(R.id.button1);
        mButton2 = (Button) root.findViewById(R.id.button2);
        mOverlay = root.findViewById(R.id.overlay);
        return root;
    }

    @Nullable
    public View getOverlay() {
        return mOverlay;
    }

    public String hitTest(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();

        if (x > mButton1.getLeft() && mButton1.getRight() > x &&
                y > mButton1.getTop() && mButton1.getBottom() > y)
        {
            return "Button 1";
        } else if (x > mButton2.getLeft() && mButton2.getRight() > x &&
                y > mButton2.getTop() && mButton2.getBottom() > y)
        {
            return "Button 2";
        } else {
            return "None";
        }
    }
}

祝你好运。

预计到达时间:样本 HitTest

/**
 * UNTESTED
 * I'm going to assume square buttons (equilateral hexagons)
 * this just calculates if the distance from the center of the button is less than its width. It may be good enough for government work.
 */
public View hitTest(MotionEvent e) {
    for (Button hex : SomeIterableThingHoldingYourButtons) { //ArrayList<Button> maybe
        float x = e.getX();
        float y = e.getY();

        if (isInHex(hex, x, y)) return hex;
     }
     return null;
}

private boolean isInHex(Button hex, float x, float y) {
    float radius = hex.getRight() - hex.getLeft() / 2;
    float centerX = hex.getLeft() + radius;
    float centerY = hex.getTop() + radius;

    float dist = FloatMath.sqrt(...) //euclidean distance

    return dist < radius;
}

关于android - 带六边形触摸区域的六边形按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28110814/

有关android - 带六边形触摸区域的六边形按钮的更多相关文章

  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 - 缺失区域;使用 :region option or export region name to ENV ['AWS_REGION' ] - 2

    我知道还有其他相同的问题,但他们没有解决我的问题。我不断收到错误:Aws::Errors::MissingRegionErrorinBooksController#create,缺少区域;使用:region选项或将区域名称导出到ENV['AWS_REGION']。但是,这是我的配置开发.rb:config.paperclip_defaults={storage::s3,s3_host_name:"s3-us-west-2.amazonaws.com",s3_credentials:{bucket:ENV['AWS_BUCKET'],access_key_id:ENV['AWS_ACCE

  3. ruby-on-rails - Rails 单选按钮 - 模型中多列的一种选择 - 2

    我希望用户从一个模型的三个选项中选择一个。即我有一个模型视频,可以被评为正面/负面/未知目前我有三列bool值(pos/neg/unknown)。这是处理这种情况的最佳方式吗?为此,表单应该是什么样的?目前我有类似的东西但显然它允许多项选择,而我试图将它限制为只有一个..怎么办? 最佳答案 如果要使用字符串列,让我们说rating。然后在你的表单中:#...#...它只允许一个选择编辑完全相同但使用radio_button_tag: 关于ruby-on-rails-Rails单选按钮-模

  4. ruby-on-rails - 如何从按钮或链接单击的 View 调用 Rails 方法 - 2

    基本上,我试图在用户单击链接(或按钮或某种类型的交互元素)时执行Rails方法。我试着把它放在View中:但这似乎没有用。它最终只是在用户甚至没有点击“添加”链接的情况下调用该函数。我也用link_to试过了,但也没用。我开始认为没有一种干净的方法可以做到这一点。无论如何,感谢您的帮助。附言。我在ApplicationController中定义了该方法,它是一个辅助方法。 最佳答案 View和Controller是相互独立的。为了使链接在Controller内执行函数调用,您需要对应用程序中的端点执行ajax调用。该路由应调用rub

  5. ruby-on-rails - 如何在 Rails 中添加禁用的提交按钮 - 2

    我在ruby​​表单中有一个提交按钮f.submitbtn_text,class:"btnbtn-onemgt12mgb12",id:"btn_id"我想在不使用任何javascript的情况下通过ruby​​禁用此按钮 最佳答案 添加disabled:true选项。f.submitbtn_text,class:"btnbtn-onemgt12mgb12",id:"btn_id",disabled:true 关于ruby-on-rails-如何在Rails中添加禁用的提交按钮,我们在St

  6. ruby-on-rails - 从 ActiveAdmin has_many 表单助手中删除 "Add new"按钮 - 2

    我在事件管理员编辑页面中有嵌套资源,但我只想允许管理员编辑现有资源的内容,而不是添加新的嵌套资源。我的代码看起来像这样:formdo|f|f.inputsdof.input:authorf.input:contentf.has_many:commentsdo|comment_form|comment_form.input:contentcomment_form.input:_destroy,as::boolean,required:false,label:'Remove'endendf.actionsend但它在输入下添加了“添加新评论”按钮。我怎样才能禁用它,并只为主窗体保留f.ac

  7. ruby-on-rails - Ruby on Rails PostGIS - 将多边形记录插入数据库 - 2

    我将RoR与PostGIS结合使用来存储位置数据。我正在尝试使用圆(例如,带半径的中心点)来存储估计位置。我试过类似的东西,但它不起作用:@location=Location.new(:place_id=>place.id,:circle=>%{ST_Buffer(ST_MakePoint(#{latitude},#{longitude})::geography,#{accuracy})})我也尝试过使用RGeo,它是出厂设置,但不确定如何准确使用它。任何帮助将不胜感激。谢谢。编辑1:我取得了一些进步。factory=RGeo::Cartesian.factorycenter_poin

  8. ruby - 按 Enter 键而不是用鞋子单击按钮(Ruby) - 2

    正如标题所暗示的那样,我只是在寻找一种无需单击即可按下Shoes中的按钮的方法。我已经搜索了论坛,但不幸的是找不到任何东西。谢谢 最佳答案 这在Windows下的红色鞋子中不起作用,因为Windows控件窃取了所有事件。不过,我设法在window下穿着绿鞋工作。举个例子['green_shoes'].each(&method(:require))Shoes.app{e=edit_linebutton("Clickme!"){alert("Youclickedme.")}keypress{|k|alert("YoupressedEnt

  9. ruby-on-rails - 具有六边形架构和 DCI 模式的框架和数据库适配器 - 2

    我尝试用Ruby设计一个基于Web的应用程序。我开发了一个简单的核心应用程序,在没有框架和数据库的情况下在六边形架构中实现DCI范例。核心六边形中有小六边形和网络,数据库,日志等适配器。每个六边形都在没有数据库和框架的情况下自行运行。在这种方法中,我如何提供与数据库模型和实体类的关系作为独立于数据库的关系。我想在将来将框架从Rails更改为Sinatra或数据库。事实上,我如何在这个核心Hexagon中实现完全隔离的rails和mongodb的数据库适配器或框架适配器。有什么想法吗? 最佳答案 ROM呢?(Ruby对象映射器)。还有

  10. ruby - 如何使用 Mechanize 保存通过单击按钮下载的文件 - 2

    我正在尝试使用Mechanize来模拟点击网页上的按钮,然后会在浏览器中启动文件下载。这是我的代码片段form=page.forms.first#=>Mechanize::Formform=agent.page.form_with(:name=>"aspnetForm")button=form.button_with(:value=>"GPXfile")ppbuttonagent.submit(form,button)pp按钮的输出是这样显示的,这意味着它是右键:#但是在发出“agent.submit(form,button)”之后,我怎样才能让Mechanize检索单击该按钮时将发送

随机推荐