WIP grabador de audio
This commit is contained in:
parent
b539f03ef6
commit
96fd70556b
4
.idea/assetWizardSettings.xml
generated
4
.idea/assetWizardSettings.xml
generated
@ -308,7 +308,7 @@
|
||||
<PersistentState>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/icons/material/materialicons/password/baseline_password_24.xml" />
|
||||
<entry key="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/icons/material/materialicons/play_arrow/baseline_play_arrow_24.xml" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
@ -318,7 +318,7 @@
|
||||
</option>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="outputName" value="baseline_password_24" />
|
||||
<entry key="outputName" value="baseline_play_arrow_24" />
|
||||
<entry key="sourceFile" value="C:\Users\erike\Downloads\face-kiss-wink-heart-solid.svg" />
|
||||
</map>
|
||||
</option>
|
||||
|
||||
18
.idea/navEditor.xml
generated
18
.idea/navEditor.xml
generated
@ -8,25 +8,13 @@
|
||||
<LayoutPositions>
|
||||
<option name="myPositions">
|
||||
<map>
|
||||
<entry key="audioDraftsFragment">
|
||||
<entry key="audiosFragment2">
|
||||
<value>
|
||||
<LayoutPositions>
|
||||
<option name="myPosition">
|
||||
<Point>
|
||||
<option name="x" value="130" />
|
||||
<option name="y" value="18" />
|
||||
</Point>
|
||||
</option>
|
||||
</LayoutPositions>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="audioRecorderMainFragment">
|
||||
<value>
|
||||
<LayoutPositions>
|
||||
<option name="myPosition">
|
||||
<Point>
|
||||
<option name="x" value="-74" />
|
||||
<option name="y" value="17" />
|
||||
<option name="x" value="40" />
|
||||
<option name="y" value="40" />
|
||||
</Point>
|
||||
</option>
|
||||
</LayoutPositions>
|
||||
|
||||
@ -40,6 +40,7 @@
|
||||
<activity android:name=".images.image_maker.ui.ImageMakerActivity" android:theme="@style/Theme.Isolaatti"/>
|
||||
<activity android:name=".images.image_chooser.ui.ImageChooserActivity" android:theme="@style/Theme.Isolaatti"/>
|
||||
<activity android:name=".profile.ui.EditProfileActivity" android:theme="@style/Theme.Isolaatti" />
|
||||
<activity android:name=".audio.recorder.ui.AudioRecorderActivity" android:theme="@style/Theme.Isolaatti" />
|
||||
<provider
|
||||
android:authorities="com.isolaatti.provider"
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
package com.isolaatti.audio.recorder.data
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "audio_drafts")
|
||||
data class AudioDraftEntity(
|
||||
@PrimaryKey val id: Long,
|
||||
val name: String,
|
||||
val audioLocalPath: String
|
||||
)
|
||||
@ -0,0 +1,21 @@
|
||||
package com.isolaatti.audio.recorder.data
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
|
||||
@Dao
|
||||
interface AudiosDraftsDao {
|
||||
@Insert
|
||||
fun insertAudioDraft(audioDraftEntity: AudioDraftEntity): Long
|
||||
|
||||
@Query("SELECT * FROM audio_drafts WHERE id = :draftId")
|
||||
fun getAudioDraftById(draftId: Long): AudioDraftEntity
|
||||
|
||||
@Query("SELECT * FROM audio_drafts WHERE id < :before ORDER BY id DESC LIMIT :count")
|
||||
fun getDrafts(count: Int, before: Long): List<AudioDraftEntity>
|
||||
|
||||
@Query("DELETE FROM audio_drafts WHERE id in (:draftIds)")
|
||||
fun deleteDrafts(draftIds: LongArray)
|
||||
}
|
||||
@ -1,6 +1,11 @@
|
||||
package com.isolaatti.audio.recorder.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
|
||||
class AudioDraftsFragment : Fragment() {
|
||||
|
||||
}
|
||||
@ -1,6 +1,219 @@
|
||||
package com.isolaatti.audio.recorder.ui
|
||||
|
||||
import androidx.activity.ComponentActivity
|
||||
import android.Manifest
|
||||
import android.content.Intent
|
||||
import android.media.MediaRecorder
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.PermissionChecker
|
||||
import androidx.core.content.PermissionChecker.PERMISSION_GRANTED
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.isolaatti.databinding.ActivityAudioRecorderBinding
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.UUID
|
||||
|
||||
@AndroidEntryPoint
|
||||
class AudioRecorderActivity : AppCompatActivity() {
|
||||
|
||||
companion object {
|
||||
const val LOG_TAG = "AudioRecorderActivity"
|
||||
}
|
||||
|
||||
private lateinit var binding: ActivityAudioRecorderBinding
|
||||
|
||||
private var audioRecorder: MediaRecorder? = null
|
||||
|
||||
private val audioUID = UUID.randomUUID()
|
||||
private lateinit var outputFile: String
|
||||
|
||||
private val requestAudioPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) {
|
||||
if(it) {
|
||||
startRecording()
|
||||
} else {
|
||||
showPermissionRationale()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
binding = ActivityAudioRecorderBinding.inflate(layoutInflater)
|
||||
|
||||
setContentView(binding.root)
|
||||
File("${filesDir.absolutePath}/audios/").let {
|
||||
if(!it.isDirectory) {
|
||||
it.mkdir()
|
||||
}
|
||||
}
|
||||
outputFile = "${filesDir.absolutePath}/audios/${audioUID}.3gp"
|
||||
|
||||
setupListeners()
|
||||
}
|
||||
|
||||
private fun checkRecordAudioPermission(): Boolean {
|
||||
return when {
|
||||
PermissionChecker.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == PERMISSION_GRANTED -> true
|
||||
ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO) -> {
|
||||
showPermissionRationale()
|
||||
false
|
||||
}
|
||||
|
||||
else -> {
|
||||
requestAudioPermissionLauncher.launch(Manifest.permission.RECORD_AUDIO)
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showPermissionRationale() {
|
||||
MaterialAlertDialogBuilder(this)
|
||||
.setTitle("Record audio permission")
|
||||
.setMessage("We need permission to access your microphone so that you can record your audio. Go to settings.")
|
||||
.setPositiveButton("Go to settings"){_, _ ->
|
||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||
intent.data = Uri.fromParts("package", packageName, null)
|
||||
startActivity(intent)
|
||||
}
|
||||
.setNegativeButton("No, thanks", null)
|
||||
.show()
|
||||
}
|
||||
|
||||
|
||||
private fun setupListeners() {
|
||||
binding.recordButton.setOnClickListener {
|
||||
if(checkRecordAudioPermission()) {
|
||||
Log.d(LOG_TAG, "Starts recording")
|
||||
startRecording()
|
||||
} else {
|
||||
Log.d(LOG_TAG, "Failed to start recording: mic permission not granted")
|
||||
}
|
||||
}
|
||||
binding.stopRecording.setOnClickListener {
|
||||
stopRecording()
|
||||
}
|
||||
|
||||
binding.cancelButton.setOnClickListener {
|
||||
discardRecording()
|
||||
}
|
||||
|
||||
binding.pauseRecording.setOnClickListener {
|
||||
pauseRecording()
|
||||
}
|
||||
|
||||
binding.acceptButton.setOnClickListener {
|
||||
acceptRecording()
|
||||
}
|
||||
|
||||
binding.playPauseButton.setOnClickListener {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// region timer
|
||||
private var timer: Job? = null
|
||||
private var timerValue = 0
|
||||
|
||||
private fun setDisplayTime(seconds: Int, showTotalTime: Boolean) {
|
||||
val stringBuilder = StringBuilder()
|
||||
|
||||
stringBuilder.append(seconds)
|
||||
|
||||
binding.time.text = stringBuilder.toString()
|
||||
}
|
||||
private fun startTimerRecorder() {
|
||||
|
||||
timer = CoroutineScope(Dispatchers.Main).launch {
|
||||
setDisplayTime(timerValue, false)
|
||||
delay(1000)
|
||||
timerValue++
|
||||
startTimerRecorder()
|
||||
}
|
||||
}
|
||||
|
||||
private fun startTimerPlayer() {
|
||||
timer?.cancel()
|
||||
timer = CoroutineScope(Dispatchers.Main).launch {
|
||||
setDisplayTime(timerValue, true)
|
||||
delay(1000)
|
||||
timerValue++
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopTimer() {
|
||||
timer?.cancel()
|
||||
}
|
||||
|
||||
// end region
|
||||
|
||||
// region record functions
|
||||
private fun startRecording() {
|
||||
audioRecorder = MediaRecorder().apply {
|
||||
setAudioSource(MediaRecorder.AudioSource.MIC)
|
||||
setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
|
||||
setOutputFile(outputFile)
|
||||
setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
|
||||
|
||||
try {
|
||||
prepare()
|
||||
start()
|
||||
timerValue = 0
|
||||
startTimerRecorder()
|
||||
binding.viewAnimator.displayedChild = 1
|
||||
} catch(e: IOException) {
|
||||
Log.e(LOG_TAG, "prepare() failed\n${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopRecording() {
|
||||
audioRecorder?.apply {
|
||||
stop()
|
||||
release()
|
||||
}
|
||||
stopTimer()
|
||||
audioRecorder = null
|
||||
|
||||
// shows third state: audio recorded
|
||||
binding.viewAnimator.displayedChild = 2
|
||||
}
|
||||
|
||||
private fun pauseRecording() {
|
||||
audioRecorder?.pause()
|
||||
stopTimer()
|
||||
}
|
||||
|
||||
private fun discardRecording(){
|
||||
File(outputFile).apply {
|
||||
try {
|
||||
delete()
|
||||
} catch(e: SecurityException) {
|
||||
Log.e(LOG_TAG, "Could not delete file\n${e.message}")
|
||||
}
|
||||
}
|
||||
binding.viewAnimator.displayedChild = 0
|
||||
}
|
||||
|
||||
// end region
|
||||
|
||||
private fun acceptRecording() {
|
||||
|
||||
}
|
||||
|
||||
private fun playPauseRecording() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
class AudioRecorderActivity : ComponentActivity() {
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
package com.isolaatti.audio.recorder.ui
|
||||
|
||||
import android.media.MediaRecorder
|
||||
import androidx.fragment.app.Fragment
|
||||
|
||||
class AudioRecorderMainFragment : Fragment() {
|
||||
|
||||
}
|
||||
@ -2,14 +2,17 @@ package com.isolaatti.database
|
||||
|
||||
import androidx.room.Database
|
||||
import androidx.room.RoomDatabase
|
||||
import com.isolaatti.audio.recorder.data.AudioDraftEntity
|
||||
import com.isolaatti.audio.recorder.data.AudiosDraftsDao
|
||||
import com.isolaatti.auth.data.local.UserInfoDao
|
||||
import com.isolaatti.auth.data.local.UserInfoEntity
|
||||
import com.isolaatti.settings.data.KeyValueDao
|
||||
import com.isolaatti.settings.data.KeyValueEntity
|
||||
|
||||
@Database(entities = [KeyValueEntity::class, UserInfoEntity::class], version = 2)
|
||||
@Database(entities = [KeyValueEntity::class, UserInfoEntity::class, AudioDraftEntity::class], version = 3)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun keyValueDao(): KeyValueDao
|
||||
abstract fun userInfoDao(): UserInfoDao
|
||||
abstract fun audioDrafts(): AudiosDraftsDao
|
||||
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package com.isolaatti.posting.posts.ui
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
@ -9,6 +10,7 @@ import androidx.core.widget.doOnTextChanged
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.isolaatti.audio.recorder.ui.AudioRecorderActivity
|
||||
import com.isolaatti.databinding.FragmentMarkdownEditingBinding
|
||||
import com.isolaatti.images.image_chooser.ui.ImageChooserContract
|
||||
import com.isolaatti.posting.link_creator.presentation.LinkCreatorViewModel
|
||||
@ -63,6 +65,10 @@ class MarkdownEditingFragment : Fragment(){
|
||||
binding.addLinkButton.setOnClickListener {
|
||||
insertLink()
|
||||
}
|
||||
|
||||
binding.addAudioButton.setOnClickListener {
|
||||
requireContext().startActivity(Intent(requireContext(), AudioRecorderActivity::class.java))
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupObservers(){
|
||||
|
||||
5
app/src/main/res/drawable/baseline_circle_24.xml
Normal file
5
app/src/main/res/drawable/baseline_circle_24.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#000000"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M12,2C6.47,2 2,6.47 2,12s4.47,10 10,10 10,-4.47 10,-10S17.53,2 12,2z"/>
|
||||
</vector>
|
||||
5
app/src/main/res/drawable/baseline_pause_24.xml
Normal file
5
app/src/main/res/drawable/baseline_pause_24.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#000000"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M6,19h4L10,5L6,5v14zM14,5v14h4L18,5h-4z"/>
|
||||
</vector>
|
||||
5
app/src/main/res/drawable/baseline_play_arrow_24.xml
Normal file
5
app/src/main/res/drawable/baseline_play_arrow_24.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#000000"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M8,5v14l11,-7z"/>
|
||||
</vector>
|
||||
5
app/src/main/res/drawable/baseline_stop_24.xml
Normal file
5
app/src/main/res/drawable/baseline_stop_24.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#000000"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M6,6h12v12H6z"/>
|
||||
</vector>
|
||||
157
app/src/main/res/layout/activity_audio_recorder.xml
Normal file
157
app/src/main/res/layout/activity_audio_recorder.xml
Normal file
@ -0,0 +1,157 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:navigationIcon="@drawable/baseline_close_24"/>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/time"
|
||||
app:layout_constraintTop_toBottomOf="@id/toolbar"
|
||||
android:layout_margin="24dp"
|
||||
style="?attr/materialCardViewFilledStyle">
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:navGraph="@navigation/audio_recorder_navigation"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
app:defaultNavHost="true"/>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/time"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toTopOf="@id/card_controls"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:textSize="24sp"
|
||||
tools:text="00:00"
|
||||
android:textAlignment="center"/>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card_controls"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
style="?attr/materialCardViewFilledStyle"
|
||||
android:layout_margin="24dp">
|
||||
|
||||
<ViewAnimator
|
||||
android:id="@+id/viewAnimator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:inAnimation="@anim/nav_default_enter_anim"
|
||||
android:outAnimation="@anim/nav_default_exit_anim">
|
||||
<!-- initial state: show only start record button-->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp">
|
||||
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/record_button"
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/baseline_circle_24"
|
||||
app:iconTint="@color/danger"
|
||||
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<!-- second state: recording-->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="8dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/stop_recording"
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/baseline_stop_24"
|
||||
app:layout_constraintEnd_toStartOf="@+id/pause_recording"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/pause_recording"
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/baseline_pause_24"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/stop_recording"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<!-- third state: recorded-->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="8dp">
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/cancel_button"
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/baseline_close_24"
|
||||
app:layout_constraintEnd_toStartOf="@+id/play_pause_button"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/play_pause_button"
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/baseline_play_arrow_24"
|
||||
app:layout_constraintEnd_toStartOf="@+id/accept_button"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/cancel_button"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/accept_button"
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/baseline_check_24"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/play_pause_button"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</ViewAnimator>
|
||||
|
||||
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@ -40,5 +40,28 @@
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
app:icon="@drawable/baseline_add_link_24" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="30dp"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
style="?attr/materialCardViewFilledStyle">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_margin="16dp">
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Audio attachment"/>
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/add_audio_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Attach audio" />
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
@ -1,14 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/audio_recorder_navigation"
|
||||
app:startDestination="@id/audioRecorderMainFragment">
|
||||
<fragment
|
||||
android:id="@+id/audioRecorderMainFragment"
|
||||
android:name="com.isolaatti.audio.recorder.ui.AudioRecorderMainFragment"
|
||||
android:label="AudioRecorderMainFragment" />
|
||||
<fragment
|
||||
android:id="@+id/audioDraftsFragment"
|
||||
android:name="com.isolaatti.audio.recorder.ui.AudioDraftsFragment"
|
||||
android:label="AudioDraftsFragment" />
|
||||
android:id="@+id/audio_recorder_navigation">
|
||||
|
||||
|
||||
</navigation>
|
||||
@ -4,4 +4,5 @@
|
||||
<color name="purple_lighter">#3F0095</color>
|
||||
<color name="surface">#1D1725</color>
|
||||
<color name="on_surface">#FFFFFF</color>
|
||||
<color name="danger">#750606</color>
|
||||
</resources>
|
||||
Loading…
x
Reference in New Issue
Block a user