Skip to content

Commit 244d24d

Browse files
committed
feat: UI for multimedia audio player
1 parent 19927e1 commit 244d24d

2 files changed

Lines changed: 392 additions & 0 deletions

File tree

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
<?xml version="1.0" encoding="utf-8"?><!--
2+
~ Copyright (c) 2026 Ashish Yadav <mailtoashish693@gmail.com>
3+
~
4+
~ This program is free software; you can redistribute it and/or modify it under
5+
~ the terms of the GNU General Public License as published by the Free Software
6+
~ Foundation; either version 3 of the License, or (at your option) any later
7+
~ version.
8+
~
9+
~ This program is distributed in the hope that it will be useful, but WITHOUT ANY
10+
~ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11+
~ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12+
~ details.
13+
~
14+
~ You should have received a copy of the GNU General Public License along with
15+
~ this program. If not, see <http://www.gnu.org/licenses/>.
16+
-->
17+
18+
<androidx.constraintlayout.widget.ConstraintLayout
19+
xmlns:android="http://schemas.android.com/apk/res/android"
20+
xmlns:app="http://schemas.android.com/apk/res-auto"
21+
xmlns:tools="http://schemas.android.com/tools"
22+
android:layout_width="match_parent"
23+
android:layout_height="match_parent"
24+
tools:ignore="UnusedResources">
25+
26+
<com.google.android.material.card.MaterialCardView
27+
android:id="@+id/waveform_card"
28+
android:layout_width="0dp"
29+
android:layout_height="0dp"
30+
android:layout_margin="8dp"
31+
app:cardCornerRadius="24dp"
32+
app:cardElevation="2dp"
33+
app:layout_constraintBottom_toBottomOf="parent"
34+
app:layout_constraintStart_toStartOf="parent"
35+
app:layout_constraintTop_toTopOf="parent"
36+
app:layout_constraintWidth_percent="0.6">
37+
38+
<FrameLayout
39+
android:layout_width="match_parent"
40+
android:layout_height="match_parent">
41+
42+
<com.ichi2.anki.multimedia.audio.AudioWaveform
43+
android:id="@+id/audio_waveform"
44+
android:layout_width="match_parent"
45+
android:layout_height="match_parent"
46+
android:visibility="visible" />
47+
48+
<com.ichi2.anki.workarounds.SafeWebViewLayout
49+
android:id="@+id/web_view_layout"
50+
android:layout_width="match_parent"
51+
android:layout_height="match_parent"
52+
android:visibility="gone" />
53+
54+
</FrameLayout>
55+
56+
</com.google.android.material.card.MaterialCardView>
57+
58+
<androidx.constraintlayout.widget.ConstraintLayout
59+
android:id="@+id/controls_area"
60+
android:layout_width="0dp"
61+
android:layout_height="match_parent"
62+
android:padding="16dp"
63+
app:layout_constraintStart_toEndOf="@id/waveform_card"
64+
app:layout_constraintEnd_toEndOf="parent"
65+
app:layout_constraintTop_toTopOf="parent"
66+
app:layout_constraintBottom_toBottomOf="parent">
67+
68+
<com.google.android.material.button.MaterialButtonToggleGroup
69+
android:id="@+id/toggle_button"
70+
android:layout_width="wrap_content"
71+
android:layout_height="wrap_content"
72+
app:checkedButton="@id/audio_wave_button"
73+
app:layout_constraintEnd_toEndOf="parent"
74+
app:layout_constraintStart_toStartOf="parent"
75+
app:layout_constraintTop_toTopOf="parent"
76+
app:selectionRequired="true"
77+
app:singleSelection="true">
78+
79+
<com.google.android.material.button.MaterialButton
80+
android:id="@+id/audio_wave_button"
81+
style="@style/Widget.Material3.Button.IconButton.Filled"
82+
android:layout_width="wrap_content"
83+
android:layout_height="wrap_content"
84+
android:insetRight="1dp"
85+
app:icon="@drawable/ic_audio_wave"
86+
android:contentDescription="@string/waveform_button_description"
87+
android:tooltipText="@string/waveform_button_description"/>
88+
89+
<com.google.android.material.button.MaterialButton
90+
android:id="@+id/content_button"
91+
style="@style/Widget.Material3.Button.IconButton.Filled"
92+
android:layout_width="wrap_content"
93+
android:layout_height="wrap_content"
94+
android:insetLeft="1dp"
95+
app:icon="@drawable/ic_notes"
96+
android:contentDescription="@string/field_content_description"
97+
android:tooltipText="@string/field_content_description" />
98+
99+
</com.google.android.material.button.MaterialButtonToggleGroup>
100+
101+
<com.google.android.material.button.MaterialButton
102+
android:id="@+id/delete_button"
103+
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
104+
android:layout_width="wrap_content"
105+
android:layout_height="wrap_content"
106+
android:layout_marginEnd="16dp"
107+
app:icon="@drawable/ic_delete"
108+
app:layout_constraintBottom_toBottomOf="@id/toggle_button"
109+
app:layout_constraintEnd_toEndOf="parent"
110+
app:layout_constraintTop_toTopOf="@id/toggle_button"
111+
android:contentDescription="@string/delete_audio_button_description"
112+
android:tooltipText="@string/delete_audio_button_description"/>
113+
114+
<LinearLayout
115+
android:id="@+id/seek_layout"
116+
android:layout_width="0dp"
117+
android:layout_height="wrap_content"
118+
android:layout_marginTop="16dp"
119+
android:orientation="vertical"
120+
android:paddingHorizontal="4dp"
121+
app:layout_constraintEnd_toEndOf="parent"
122+
app:layout_constraintStart_toStartOf="parent"
123+
app:layout_constraintTop_toBottomOf="@id/toggle_button"
124+
app:layout_constraintBottom_toTopOf="@id/playback_controls">
125+
126+
<com.google.android.material.slider.Slider
127+
android:id="@+id/seek_bar"
128+
android:layout_width="match_parent"
129+
android:layout_height="wrap_content"
130+
app:thumbHeight="24dp"
131+
app:tickVisible="false" />
132+
133+
<LinearLayout
134+
android:layout_width="match_parent"
135+
android:layout_height="wrap_content"
136+
android:orientation="horizontal">
137+
138+
<com.google.android.material.textview.MaterialTextView
139+
android:id="@+id/current_time_text"
140+
android:layout_width="0dp"
141+
android:layout_height="wrap_content"
142+
android:layout_weight="1"
143+
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
144+
tools:text="00:01:23" />
145+
146+
<com.google.android.material.textview.MaterialTextView
147+
android:id="@+id/duration_text"
148+
android:layout_width="wrap_content"
149+
android:layout_height="wrap_content"
150+
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
151+
tools:text="00:03:55" />
152+
153+
</LinearLayout>
154+
155+
</LinearLayout>
156+
157+
<LinearLayout
158+
android:id="@+id/playback_controls"
159+
android:layout_width="match_parent"
160+
android:layout_height="wrap_content"
161+
android:layout_marginTop="16dp"
162+
android:gravity="center"
163+
android:orientation="horizontal"
164+
app:layout_constraintEnd_toEndOf="parent"
165+
app:layout_constraintStart_toStartOf="parent"
166+
app:layout_constraintTop_toBottomOf="@id/seek_layout"
167+
app:layout_constraintBottom_toBottomOf="parent">
168+
169+
<com.google.android.material.button.MaterialButton
170+
android:id="@+id/replay_button"
171+
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
172+
android:layout_width="wrap_content"
173+
android:layout_height="wrap_content"
174+
app:icon="@drawable/baseline_replay_5_24" />
175+
176+
<com.google.android.material.button.MaterialButton
177+
android:id="@+id/play_pause_button"
178+
style="@style/Widget.Material3.Button"
179+
android:layout_width="wrap_content"
180+
android:layout_height="wrap_content"
181+
android:layout_marginHorizontal="8dp"
182+
android:minWidth="140dp"
183+
android:minHeight="64dp"
184+
android:text="@string/play_recording"
185+
android:textSize="18sp"
186+
app:icon="@drawable/ic_play"
187+
app:iconPadding="8dp"
188+
app:iconSize="28dp" />
189+
190+
<com.google.android.material.button.MaterialButton
191+
android:id="@+id/forward_button"
192+
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
193+
android:layout_width="wrap_content"
194+
android:layout_height="wrap_content"
195+
app:icon="@drawable/baseline_forward_5_24" />
196+
197+
</LinearLayout>
198+
199+
</androidx.constraintlayout.widget.ConstraintLayout>
200+
201+
</androidx.constraintlayout.widget.ConstraintLayout>
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
<?xml version="1.0" encoding="utf-8"?><!--
2+
~ Copyright (c) 2026 Ashish Yadav <mailtoashish693@gmail.com>
3+
~
4+
~ This program is free software; you can redistribute it and/or modify it under
5+
~ the terms of the GNU General Public License as published by the Free Software
6+
~ Foundation; either version 3 of the License, or (at your option) any later
7+
~ version.
8+
~
9+
~ This program is distributed in the hope that it will be useful, but WITHOUT ANY
10+
~ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11+
~ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12+
~ details.
13+
~
14+
~ You should have received a copy of the GNU General Public License along with
15+
~ this program. If not, see <http://www.gnu.org/licenses/>.
16+
-->
17+
18+
<androidx.constraintlayout.widget.ConstraintLayout
19+
xmlns:android="http://schemas.android.com/apk/res/android"
20+
xmlns:app="http://schemas.android.com/apk/res-auto"
21+
xmlns:tools="http://schemas.android.com/tools"
22+
android:layout_width="match_parent"
23+
android:layout_height="match_parent"
24+
tools:ignore="UnusedResources">
25+
26+
<com.google.android.material.card.MaterialCardView
27+
android:id="@+id/waveform_card"
28+
android:layout_width="0dp"
29+
android:layout_height="0dp"
30+
android:layout_margin="8dp"
31+
app:cardCornerRadius="24dp"
32+
app:cardElevation="2dp"
33+
app:layout_constraintEnd_toEndOf="parent"
34+
app:layout_constraintHeight_percent="0.7"
35+
app:layout_constraintStart_toStartOf="parent"
36+
app:layout_constraintTop_toTopOf="parent">
37+
38+
<FrameLayout
39+
android:layout_width="match_parent"
40+
android:layout_height="match_parent">
41+
42+
<com.ichi2.anki.multimedia.audio.AudioWaveform
43+
android:id="@+id/audio_waveform"
44+
android:layout_width="match_parent"
45+
android:layout_height="match_parent"
46+
android:visibility="visible" />
47+
48+
<com.ichi2.anki.workarounds.SafeWebViewLayout
49+
android:id="@+id/web_view_layout"
50+
android:layout_width="match_parent"
51+
android:layout_height="match_parent"
52+
android:visibility="gone" />
53+
54+
</FrameLayout>
55+
56+
</com.google.android.material.card.MaterialCardView>
57+
58+
<androidx.constraintlayout.widget.ConstraintLayout
59+
android:id="@+id/controls_area"
60+
android:layout_width="match_parent"
61+
android:layout_height="0dp"
62+
android:layout_margin="8dp"
63+
app:layout_constraintBottom_toBottomOf="parent"
64+
app:layout_constraintTop_toBottomOf="@id/waveform_card">
65+
66+
<com.google.android.material.button.MaterialButtonToggleGroup
67+
android:id="@+id/toggle_button"
68+
android:layout_width="wrap_content"
69+
android:layout_height="wrap_content"
70+
app:checkedButton="@id/audio_wave_button"
71+
app:layout_constraintEnd_toEndOf="parent"
72+
app:layout_constraintStart_toStartOf="parent"
73+
app:layout_constraintTop_toTopOf="parent"
74+
app:selectionRequired="true"
75+
app:singleSelection="true">
76+
77+
<com.google.android.material.button.MaterialButton
78+
android:id="@+id/audio_wave_button"
79+
style="@style/Widget.Material3.Button.IconButton.Filled"
80+
android:layout_width="wrap_content"
81+
android:layout_height="wrap_content"
82+
android:insetRight="1dp"
83+
app:icon="@drawable/ic_audio_wave" />
84+
85+
<com.google.android.material.button.MaterialButton
86+
android:id="@+id/content_button"
87+
style="@style/Widget.Material3.Button.IconButton.Filled"
88+
android:layout_width="wrap_content"
89+
android:layout_height="wrap_content"
90+
android:insetLeft="1dp"
91+
app:icon="@drawable/ic_notes" />
92+
93+
</com.google.android.material.button.MaterialButtonToggleGroup>
94+
95+
<com.google.android.material.button.MaterialButton
96+
android:id="@+id/delete_button"
97+
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
98+
android:layout_width="wrap_content"
99+
android:layout_height="wrap_content"
100+
android:layout_marginEnd="16dp"
101+
app:icon="@drawable/ic_delete"
102+
app:layout_constraintBottom_toBottomOf="@id/toggle_button"
103+
app:layout_constraintEnd_toEndOf="parent"
104+
app:layout_constraintTop_toTopOf="@id/toggle_button" />
105+
106+
<LinearLayout
107+
android:id="@+id/seek_layout"
108+
android:layout_width="0dp"
109+
android:layout_height="wrap_content"
110+
android:layout_marginTop="16dp"
111+
android:orientation="vertical"
112+
android:paddingHorizontal="4dp"
113+
app:layout_constraintEnd_toEndOf="parent"
114+
app:layout_constraintStart_toStartOf="parent"
115+
app:layout_constraintTop_toBottomOf="@id/toggle_button">
116+
117+
<com.google.android.material.slider.Slider
118+
android:id="@+id/seek_bar"
119+
android:layout_width="match_parent"
120+
android:layout_height="wrap_content"
121+
app:thumbHeight="24dp"
122+
app:tickVisible="false" />
123+
124+
<LinearLayout
125+
android:layout_width="match_parent"
126+
android:layout_height="wrap_content"
127+
android:orientation="horizontal">
128+
129+
<com.google.android.material.textview.MaterialTextView
130+
android:id="@+id/current_time_text"
131+
android:layout_width="0dp"
132+
android:layout_height="wrap_content"
133+
android:layout_weight="1"
134+
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
135+
tools:text="00:01:23" />
136+
137+
<com.google.android.material.textview.MaterialTextView
138+
android:id="@+id/duration_text"
139+
android:layout_width="wrap_content"
140+
android:layout_height="wrap_content"
141+
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
142+
tools:text="00:03:55" />
143+
144+
</LinearLayout>
145+
146+
</LinearLayout>
147+
148+
<LinearLayout
149+
android:id="@+id/playback_controls"
150+
android:layout_width="match_parent"
151+
android:layout_height="0dp"
152+
android:gravity="center"
153+
android:orientation="horizontal"
154+
app:layout_constraintBottom_toBottomOf="parent"
155+
app:layout_constraintEnd_toEndOf="parent"
156+
app:layout_constraintStart_toStartOf="parent"
157+
app:layout_constraintTop_toBottomOf="@id/seek_layout">
158+
159+
<com.google.android.material.button.MaterialButton
160+
android:id="@+id/replay_button"
161+
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
162+
android:layout_width="wrap_content"
163+
android:layout_height="wrap_content"
164+
app:icon="@drawable/baseline_replay_5_24" />
165+
166+
<com.google.android.material.button.MaterialButton
167+
android:id="@+id/play_pause_button"
168+
style="@style/Widget.Material3.Button"
169+
android:layout_width="wrap_content"
170+
android:layout_height="wrap_content"
171+
android:layout_marginHorizontal="24dp"
172+
android:minWidth="140dp"
173+
android:minHeight="64dp"
174+
android:text="@string/play_recording"
175+
android:textSize="18sp"
176+
app:icon="@drawable/ic_play"
177+
app:iconPadding="8dp"
178+
app:iconSize="28dp" />
179+
180+
<com.google.android.material.button.MaterialButton
181+
android:id="@+id/forward_button"
182+
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
183+
android:layout_width="wrap_content"
184+
android:layout_height="wrap_content"
185+
app:icon="@drawable/baseline_forward_5_24" />
186+
187+
</LinearLayout>
188+
189+
</androidx.constraintlayout.widget.ConstraintLayout>
190+
191+
</androidx.constraintlayout.widget.ConstraintLayout>

0 commit comments

Comments
 (0)