diff --git a/.gitea/workflows/android.yml b/.gitea/workflows/android.yml index da46dfd..668cb21 100644 --- a/.gitea/workflows/android.yml +++ b/.gitea/workflows/android.yml @@ -1,8 +1,6 @@ name: Android on: - push: - pull_request: release: types: [published] workflow_dispatch: @@ -22,8 +20,6 @@ jobs: - uses: android-actions/setup-android@v3 # Gitea's act resolver cannot peel the annotated v4 tag alias. - uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 - with: - cache-read-only: ${{ gitea.event_name == 'pull_request' }} - name: Install Android SDK packages run: sdkmanager "platforms;android-35" "build-tools;35.0.0" - name: Lint and test diff --git a/android/app/src/main/java/io/github/transui/android/PushToTalkButton.java b/android/app/src/main/java/io/github/transui/android/PushToTalkButton.java index a24542c..cce2859 100644 --- a/android/app/src/main/java/io/github/transui/android/PushToTalkButton.java +++ b/android/app/src/main/java/io/github/transui/android/PushToTalkButton.java @@ -1,17 +1,34 @@ package io.github.transui.android; import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.ImageButton; public final class PushToTalkButton extends ImageButton { + enum IconMode { + APPS, + STOP_CIRCLE + } + + private final Paint iconPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Runnable pressedAction; private Runnable releasedAction; private boolean trackingPress; + private IconMode iconMode = IconMode.STOP_CIRCLE; public PushToTalkButton(Context context, AttributeSet attributes) { super(context, attributes); + iconPaint.setColor(context.getColor(R.color.on_signal)); + setImageDrawable(null); + } + + void setIconMode(IconMode iconMode) { + this.iconMode = iconMode; + setImageDrawable(null); + invalidate(); } void setPushToTalkActions(Runnable pressedAction, Runnable releasedAction) { @@ -55,4 +72,48 @@ public final class PushToTalkButton extends ImageButton { public boolean performClick() { return super.performClick(); } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + float contentWidth = getWidth() - getPaddingLeft() - getPaddingRight(); + float contentHeight = getHeight() - getPaddingTop() - getPaddingBottom(); + float size = Math.min(contentWidth, contentHeight); + float centerX = getWidth() / 2f; + float centerY = getHeight() / 2f; + if (iconMode == IconMode.APPS) { + drawAppsIcon(canvas, centerX, centerY, size); + } else { + drawStopCircleIcon(canvas, centerX, centerY, size); + } + } + + private void drawAppsIcon(Canvas canvas, float centerX, float centerY, float size) { + iconPaint.setStyle(Paint.Style.FILL); + float spacing = size * 0.27f; + float radius = size * 0.09f; + for (int row = -1; row <= 1; row++) { + for (int column = -1; column <= 1; column++) { + canvas.drawCircle( + centerX + column * spacing, + centerY + row * spacing, + radius, + iconPaint); + } + } + } + + private void drawStopCircleIcon(Canvas canvas, float centerX, float centerY, float size) { + iconPaint.setStyle(Paint.Style.STROKE); + iconPaint.setStrokeWidth(size * 0.12f); + canvas.drawCircle(centerX, centerY, size * 0.42f, iconPaint); + iconPaint.setStyle(Paint.Style.FILL); + float squareHalfSize = size * 0.17f; + canvas.drawRect( + centerX - squareHalfSize, + centerY - squareHalfSize, + centerX + squareHalfSize, + centerY + squareHalfSize, + iconPaint); + } } diff --git a/android/app/src/main/java/io/github/transui/android/SpeechRecognitionActivity.java b/android/app/src/main/java/io/github/transui/android/SpeechRecognitionActivity.java index 58403c3..a30145f 100644 --- a/android/app/src/main/java/io/github/transui/android/SpeechRecognitionActivity.java +++ b/android/app/src/main/java/io/github/transui/android/SpeechRecognitionActivity.java @@ -83,13 +83,13 @@ public final class SpeechRecognitionActivity extends Activity { if (config.pushToTalk) { record.setBackgroundResource(R.drawable.voice_pill_button); resizeRecordButton(132, 64, 16); - record.setImageResource(R.drawable.ic_apps); + record.setIconMode(PushToTalkButton.IconMode.APPS); record.setContentDescription(getString(R.string.hold_to_talk)); record.setPushToTalkActions(this::startRecording, this::stopRecording); } else { record.setBackgroundResource(R.drawable.voice_primary_button); resizeRecordButton(64, 64, 19); - record.setImageResource(R.drawable.ic_stop); + record.setIconMode(PushToTalkButton.IconMode.STOP_CIRCLE); record.setContentDescription(getString(R.string.stop)); record.setOnClickListener(view -> stopRecording()); } @@ -198,7 +198,9 @@ public final class SpeechRecognitionActivity extends Activity { public void onRecording() { runOnUiThread(() -> { status.setText(R.string.listening); - if (!config.pushToTalk) record.setImageResource(R.drawable.ic_stop); + if (!config.pushToTalk) { + record.setIconMode(PushToTalkButton.IconMode.STOP_CIRCLE); + } recordingStartedAt = SystemClock.elapsedRealtime(); elapsed.setText(R.string.elapsed_zero); handler.post(updateElapsed); diff --git a/android/app/src/main/java/io/github/transui/android/TransuiInputMethodService.java b/android/app/src/main/java/io/github/transui/android/TransuiInputMethodService.java index 56c0984..6a947cb 100644 --- a/android/app/src/main/java/io/github/transui/android/TransuiInputMethodService.java +++ b/android/app/src/main/java/io/github/transui/android/TransuiInputMethodService.java @@ -112,13 +112,13 @@ public final class TransuiInputMethodService extends InputMethodService { if (config.pushToTalk) { record.setBackgroundResource(R.drawable.voice_pill_button); resizeRecordButton(132, 64, 16); - record.setImageResource(R.drawable.ic_apps); + record.setIconMode(PushToTalkButton.IconMode.APPS); record.setContentDescription(getString(R.string.hold_to_talk)); record.setPushToTalkActions(this::startRecording, this::stopRecording); } else { record.setBackgroundResource(R.drawable.voice_primary_button); resizeRecordButton(64, 64, 19); - record.setImageResource(R.drawable.ic_stop); + record.setIconMode(PushToTalkButton.IconMode.STOP_CIRCLE); record.setContentDescription(getString(R.string.stop)); record.setOnClickListener(view -> stopRecording()); } @@ -180,7 +180,9 @@ public final class TransuiInputMethodService extends InputMethodService { public void onRecording() { handler.post(() -> { status.setText(R.string.listening); - if (!config.pushToTalk) record.setImageResource(R.drawable.ic_stop); + if (!config.pushToTalk) { + record.setIconMode(PushToTalkButton.IconMode.STOP_CIRCLE); + } }); } diff --git a/android/app/src/main/res/drawable/ic_apps.xml b/android/app/src/main/res/drawable/ic_apps.xml deleted file mode 100644 index c319fc7..0000000 --- a/android/app/src/main/res/drawable/ic_apps.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - diff --git a/android/app/src/main/res/drawable/ic_stop.xml b/android/app/src/main/res/drawable/ic_stop.xml deleted file mode 100644 index 9f562dc..0000000 --- a/android/app/src/main/res/drawable/ic_stop.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - diff --git a/android/app/src/main/res/layout/recognition_panel.xml b/android/app/src/main/res/layout/recognition_panel.xml index ea74c37..be50110 100644 --- a/android/app/src/main/res/layout/recognition_panel.xml +++ b/android/app/src/main/res/layout/recognition_panel.xml @@ -60,8 +60,7 @@ android:layout_marginTop="14dp" android:background="@drawable/voice_primary_button" android:contentDescription="@string/stop" - android:padding="16dp" - android:src="@drawable/ic_stop" /> + android:padding="16dp" />