首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android Button 點擊區域變圓形:自定義 View 覆寫 onTouchEvent 實現

     編輯:程式設計綜合問答

核心思路

Button 默認矩形點擊區域由 View.onTouchEvent 判斷。**繼承 Button/AppCompatButton,覆寫 onTouchEvent,按幾何圓形判斷觸摸點是否在半徑內**。

完整自定義 RoundButton

public class RoundButton extends AppCompatButton {

    public RoundButton(Context context) { super(context); }
    public RoundButton(Context context, AttributeSet attrs) { super(context, attrs); }
    public RoundButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 1. 獲取觸摸點相對 View 左上角坐標
        float x = event.getX();
        float y = event.getY();

        // 2. 計算 View 中心點與半徑(取寬高較小值一半,保證正圓)
        float cx = getWidth() / 2f;
        float cy = getHeight() / 2f;
        float radius = Math.min(cx, cy);

        // 3. 判斷點是否在圓內:距離平方 <= 半徑平方
        float dx = x - cx;
        float dy = y - cy;
        boolean inside = (dx * dx + dy * dy) <= (radius * radius);

        // 4. 若不在圓內,直接返回 false → 事件向下傳遞/忽略
        if (!inside) {
            return false;
        }

        // 5. 在圓內,交給父類處理(包含點擊反饋、點擊監聽器觸發)
        return super.onTouchEvent(event);
    }
}

XML 中使用

<com.example.widget.RoundButton
    android:id="@+id/btnRound"
    android:layout_width="80dp"
    android:layout_height="80dp"
    android:background="@drawable/bg_circle_blue"
    android:text="GO"
    android:textColor="@android:color/white" />

配合圓形背景 Drawable

<!-- res/drawable/bg_circle_blue.xml -->
<shape xmlns:android="https://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="#2196F3" />
    <stroke android:width="2dp" android:color="#1976D2" />
</shape>

進階:支持 XML 屬性配置半徑偏移

// attrs.xml
<declare-styleable name="RoundButton">
    <attr name="touchRadiusRatio" format="float" /> <!-- 0.5 = 正圓,<0.5 為橢圓內切圓 -->
</declare-styleable>

// RoundButton.java
private float touchRadiusRatio = 0.5f;

public RoundButton(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundButton);
    touchRadiusRatio = a.getFloat(R.styleable.RoundButton_touchRadiusRatio, 0.5f);
    a.recycle();
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    float cx = getWidth() / 2f;
    float cy = getHeight() / 2f;
    float radius = Math.min(cx, cy) * touchRadiusRatio;
    // ... 後續判斷同前
}

對比:其他常見但不完美的方案

方案缺點
只設置圓形背景 android:background點擊區域仍為矩形,四角空白處仍能觸發點擊
setTouchDelegate 擴大/縮小觸摸區域只能矩形區域,無法實現圓形
覆寫 dispatchTouchEvent同 onTouchEvent,但更早攔截,易影響父佈局攔截邏輯
自定義 View 繪製 + 手動判斷需自行實現文字、圖標、狀態(pressed/disabled)繪製,工作量大

總結

  • **繼承 Button + 覆寫 onTouchEvent + 幾何判斷** 是成本最低、兼容性最好、保留原生按鈕行為(ripple、文字、圖標、狀態)的方案。
  • 配合 shape=oval 背景,視覺與交互完美一致。

幾行代碼,讓方形 Button 真正變身圓形點擊區域。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved