parent
76aaaddb5a
commit
e6e3df701d
|
@ -22,6 +22,7 @@ interface CreatorCommunityApi {
|
||||||
@POST("/creator-community")
|
@POST("/creator-community")
|
||||||
@Multipart
|
@Multipart
|
||||||
fun createCommunityPost(
|
fun createCommunityPost(
|
||||||
|
@Part audioFile: MultipartBody.Part?,
|
||||||
@Part postImage: MultipartBody.Part?,
|
@Part postImage: MultipartBody.Part?,
|
||||||
@Part("request") request: RequestBody,
|
@Part("request") request: RequestBody,
|
||||||
@Header("Authorization") authHeader: String
|
@Header("Authorization") authHeader: String
|
||||||
|
|
|
@ -75,10 +75,12 @@ class CreatorCommunityRepository(private val api: CreatorCommunityApi) {
|
||||||
)
|
)
|
||||||
|
|
||||||
fun createCommunityPost(
|
fun createCommunityPost(
|
||||||
|
audioFile: MultipartBody.Part?,
|
||||||
postImage: MultipartBody.Part?,
|
postImage: MultipartBody.Part?,
|
||||||
request: RequestBody,
|
request: RequestBody,
|
||||||
token: String
|
token: String
|
||||||
) = api.createCommunityPost(
|
) = api.createCommunityPost(
|
||||||
|
audioFile = audioFile,
|
||||||
postImage = postImage,
|
postImage = postImage,
|
||||||
request = request,
|
request = request,
|
||||||
authHeader = token
|
authHeader = token
|
||||||
|
|
|
@ -24,10 +24,11 @@ import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
import kr.co.vividnext.sodalive.databinding.ActivityCreatorCommunityWriteBinding
|
import kr.co.vividnext.sodalive.databinding.ActivityCreatorCommunityWriteBinding
|
||||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
class CreatorCommunityWriteActivity : BaseActivity<ActivityCreatorCommunityWriteBinding>(
|
class CreatorCommunityWriteActivity : BaseActivity<ActivityCreatorCommunityWriteBinding>(
|
||||||
ActivityCreatorCommunityWriteBinding::inflate
|
ActivityCreatorCommunityWriteBinding::inflate
|
||||||
) {
|
), RecordingVoiceFragment.OnAudioRecordedListener {
|
||||||
|
|
||||||
private val viewModel: CreatorCommunityWriteViewModel by inject()
|
private val viewModel: CreatorCommunityWriteViewModel by inject()
|
||||||
|
|
||||||
|
@ -51,7 +52,10 @@ class CreatorCommunityWriteActivity : BaseActivity<ActivityCreatorCommunityWrite
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.setImageUri(fileUri)
|
viewModel.setImageUri(fileUri)
|
||||||
|
|
||||||
|
binding.llRecordAudio.visibility = View.VISIBLE
|
||||||
} else {
|
} else {
|
||||||
|
binding.llRecordAudio.visibility = View.GONE
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
this,
|
this,
|
||||||
"잘못된 파일입니다.\n다시 선택해 주세요.",
|
"잘못된 파일입니다.\n다시 선택해 주세요.",
|
||||||
|
@ -59,6 +63,7 @@ class CreatorCommunityWriteActivity : BaseActivity<ActivityCreatorCommunityWrite
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
} else if (resultCode == ImagePicker.RESULT_ERROR) {
|
} else if (resultCode == ImagePicker.RESULT_ERROR) {
|
||||||
|
binding.llRecordAudio.visibility = View.GONE
|
||||||
Toast.makeText(this, ImagePicker.getError(data), Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, ImagePicker.getError(data), Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,12 +79,28 @@ class CreatorCommunityWriteActivity : BaseActivity<ActivityCreatorCommunityWrite
|
||||||
bindData()
|
bindData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
deleteAudioFile()
|
||||||
|
super.onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deleteAudioFile() {
|
||||||
|
if (viewModel.audioFile != null && viewModel.audioFile!!.exists()) {
|
||||||
|
viewModel.audioFile?.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun setupView() {
|
override fun setupView() {
|
||||||
loadingDialog = LoadingDialog(this, layoutInflater)
|
loadingDialog = LoadingDialog(this, layoutInflater)
|
||||||
|
|
||||||
binding.toolbar.tvBack.text = "게시글 등록"
|
binding.toolbar.tvBack.text = "게시글 등록"
|
||||||
binding.toolbar.tvBack.setOnClickListener { finish() }
|
binding.toolbar.tvBack.setOnClickListener { finish() }
|
||||||
|
|
||||||
|
binding.tvRecordAudio.setOnClickListener {
|
||||||
|
val fragment = RecordingVoiceFragment()
|
||||||
|
fragment.show(supportFragmentManager, fragment.tag)
|
||||||
|
}
|
||||||
|
|
||||||
binding.ivPhotoPicker.setOnClickListener {
|
binding.ivPhotoPicker.setOnClickListener {
|
||||||
ImagePicker.with(this)
|
ImagePicker.with(this)
|
||||||
.crop()
|
.crop()
|
||||||
|
@ -332,4 +353,10 @@ class CreatorCommunityWriteActivity : BaseActivity<ActivityCreatorCommunityWrite
|
||||||
R.drawable.bg_round_corner_6_7_13181b
|
R.drawable.bg_round_corner_6_7_13181b
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onAudioRecorded(file: File) {
|
||||||
|
deleteAudioFile()
|
||||||
|
binding.tvRecordAudio.text = file.name
|
||||||
|
viewModel.audioFile = file
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ class CreatorCommunityWriteViewModel(
|
||||||
|
|
||||||
var price = 0
|
var price = 0
|
||||||
var content = ""
|
var content = ""
|
||||||
|
var audioFile: File? = null
|
||||||
private var imageUri: Uri? = null
|
private var imageUri: Uri? = null
|
||||||
|
|
||||||
fun setAdult(isAdult: Boolean) {
|
fun setAdult(isAdult: Boolean) {
|
||||||
|
@ -110,8 +111,37 @@ class CreatorCommunityWriteViewModel(
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val multipartAudioFile = if (audioFile != null) {
|
||||||
|
MultipartBody.Part.createFormData(
|
||||||
|
"audioFile",
|
||||||
|
audioFile!!.name,
|
||||||
|
body = object : RequestBody() {
|
||||||
|
override fun contentType(): MediaType {
|
||||||
|
return "audio/*".toMediaType()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeTo(sink: BufferedSink) {
|
||||||
|
audioFile!!.inputStream().use { inputStream ->
|
||||||
|
val buffer = ByteArray(512)
|
||||||
|
var bytesRead: Int
|
||||||
|
while (inputStream.read(buffer).also { bytesRead = it } != -1) {
|
||||||
|
sink.write(buffer, 0, bytesRead)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun contentLength(): Long {
|
||||||
|
return audioFile!!.length()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
compositeDisposable.add(
|
compositeDisposable.add(
|
||||||
repository.createCommunityPost(
|
repository.createCommunityPost(
|
||||||
|
audioFile = multipartAudioFile,
|
||||||
postImage = postImage,
|
postImage = postImage,
|
||||||
request = requestJson.toRequestBody("text/plain".toMediaType()),
|
request = requestJson.toRequestBody("text/plain".toMediaType()),
|
||||||
token = "Bearer ${SharedPreferenceManager.token}"
|
token = "Bearer ${SharedPreferenceManager.token}"
|
||||||
|
|
|
@ -0,0 +1,300 @@
|
||||||
|
package kr.co.vividnext.sodalive.explorer.profile.creator_community.write
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Dialog
|
||||||
|
import android.content.Context
|
||||||
|
import android.media.MediaPlayer
|
||||||
|
import android.media.MediaRecorder
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.CountDownTimer
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.Toast
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
|
import kr.co.vividnext.sodalive.databinding.FragmentRecordingVoiceBinding
|
||||||
|
import java.io.File
|
||||||
|
import java.io.IOException
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
class RecordingVoiceFragment : BottomSheetDialogFragment() {
|
||||||
|
|
||||||
|
private var listener: OnAudioRecordedListener? = null
|
||||||
|
private var countDownTimer: CountDownTimer? = null
|
||||||
|
private var mediaRecorder: MediaRecorder? = null
|
||||||
|
private var mediaPlayer: MediaPlayer? = null
|
||||||
|
private var fileNameMedia = ""
|
||||||
|
|
||||||
|
private var second = -1
|
||||||
|
private var minute = 0
|
||||||
|
private var hour = 0
|
||||||
|
|
||||||
|
private lateinit var binding: FragmentRecordingVoiceBinding
|
||||||
|
|
||||||
|
interface OnAudioRecordedListener {
|
||||||
|
fun onAudioRecorded(file: File)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAttach(context: Context) {
|
||||||
|
super.onAttach(context)
|
||||||
|
if (context is OnAudioRecordedListener) {
|
||||||
|
listener = context
|
||||||
|
} else {
|
||||||
|
throw RuntimeException("$context must implement OnAudioRecordedListener")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
|
val dialog = super.onCreateDialog(savedInstanceState)
|
||||||
|
|
||||||
|
dialog.setOnShowListener {
|
||||||
|
val d = it as BottomSheetDialog
|
||||||
|
val bottomSheet = d.findViewById<FrameLayout>(
|
||||||
|
com.google.android.material.R.id.design_bottom_sheet
|
||||||
|
)
|
||||||
|
if (bottomSheet != null) {
|
||||||
|
BottomSheetBehavior.from(bottomSheet).state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dialog
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
binding = FragmentRecordingVoiceBinding.inflate(inflater, container, false)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
binding.ivClose.setOnClickListener { dismiss() }
|
||||||
|
binding.ivRecordStart.setOnClickListener {
|
||||||
|
fileNameMedia = requireActivity().filesDir.path +
|
||||||
|
"/record_community_voice_${System.currentTimeMillis()}.m4a"
|
||||||
|
|
||||||
|
val fileMedia = File(fileNameMedia)
|
||||||
|
if (!fileMedia.exists()) {
|
||||||
|
try {
|
||||||
|
fileMedia.createNewFile()
|
||||||
|
startRecording()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
Toast.makeText(requireActivity(), R.string.retry, Toast.LENGTH_LONG).show()
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.ivRecordStop.setOnClickListener { stopRecording() }
|
||||||
|
binding.ivRecordPlay.setOnClickListener { startPlaying() }
|
||||||
|
binding.ivRecordPause.setOnClickListener { stopPlaying() }
|
||||||
|
|
||||||
|
binding.tvDelete.setOnClickListener {
|
||||||
|
deleteAudioFile()
|
||||||
|
|
||||||
|
binding.ivRecordStart.visibility = View.VISIBLE
|
||||||
|
binding.llRetryOrComplete.visibility = View.GONE
|
||||||
|
binding.rlRecordPlay.visibility = View.GONE
|
||||||
|
binding.soundVisualizer.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.tvRetryRecord.setOnClickListener {
|
||||||
|
deleteAudioFile()
|
||||||
|
|
||||||
|
binding.ivRecordStart.visibility = View.VISIBLE
|
||||||
|
binding.llRetryOrComplete.visibility = View.GONE
|
||||||
|
binding.rlRecordPlay.visibility = View.GONE
|
||||||
|
binding.soundVisualizer.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.tvComplete.setOnClickListener {
|
||||||
|
listener?.onAudioRecorded(file = File(fileNameMedia))
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDetach() {
|
||||||
|
super.onDetach()
|
||||||
|
listener = null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
releaseMediaPlayer()
|
||||||
|
releaseMediaRecorder()
|
||||||
|
deleteAudioFile()
|
||||||
|
|
||||||
|
super.onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deleteAudioFile() {
|
||||||
|
if (fileNameMedia.isNotBlank()) {
|
||||||
|
val fileMedia = File(fileNameMedia)
|
||||||
|
if (fileMedia.exists()) {
|
||||||
|
fileMedia.delete()
|
||||||
|
}
|
||||||
|
fileNameMedia = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startRecording() {
|
||||||
|
releaseMediaRecorder()
|
||||||
|
|
||||||
|
// safety check, don't start a new recording if one is already going
|
||||||
|
mediaRecorder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
|
MediaRecorder(requireContext())
|
||||||
|
} else {
|
||||||
|
MediaRecorder()
|
||||||
|
}.apply {
|
||||||
|
setAudioSource(MediaRecorder.AudioSource.MIC)
|
||||||
|
setOutputFile(fileNameMedia)
|
||||||
|
setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
|
||||||
|
setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
|
||||||
|
setAudioEncodingBitRate(192000)
|
||||||
|
setAudioSamplingRate(48000)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
mediaRecorder!!.prepare()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Toast.makeText(requireActivity(), R.string.retry, Toast.LENGTH_LONG).show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mediaRecorder!!.start()
|
||||||
|
binding.ivRecordStart.visibility = View.GONE
|
||||||
|
binding.ivRecordStop.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
startCountDownTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun releaseMediaRecorder() {
|
||||||
|
if (mediaRecorder != null) {
|
||||||
|
// stop recording and free up resources
|
||||||
|
mediaRecorder!!.stop()
|
||||||
|
mediaRecorder!!.reset()
|
||||||
|
mediaRecorder!!.release()
|
||||||
|
|
||||||
|
mediaRecorder = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun stopRecording() {
|
||||||
|
releaseMediaRecorder()
|
||||||
|
stopCountDownTimer()
|
||||||
|
|
||||||
|
binding.ivRecordStop.visibility = View.GONE
|
||||||
|
binding.rlRecordPlay.visibility = View.VISIBLE
|
||||||
|
binding.llRetryOrComplete.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startPlaying() {
|
||||||
|
if (mediaPlayer == null) {
|
||||||
|
mediaPlayer = MediaPlayer()
|
||||||
|
mediaPlayer!!.reset()
|
||||||
|
|
||||||
|
mediaPlayer!!.setOnCompletionListener {
|
||||||
|
releaseMediaPlayer()
|
||||||
|
stopCountDownTimer()
|
||||||
|
|
||||||
|
binding.tvDelete.visibility = View.VISIBLE
|
||||||
|
binding.ivRecordPlay.visibility = View.VISIBLE
|
||||||
|
binding.llRetryOrComplete.visibility = View.VISIBLE
|
||||||
|
binding.ivRecordPause.visibility = View.GONE
|
||||||
|
binding.soundVisualizer.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
mediaPlayer!!.setOnPreparedListener {
|
||||||
|
binding.soundVisualizer.visibility = View.VISIBLE
|
||||||
|
binding.soundVisualizer.setAudioSessionId(mediaPlayer!!.audioSessionId)
|
||||||
|
it.start()
|
||||||
|
|
||||||
|
startCountDownTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
mediaPlayer!!.setDataSource(fileNameMedia)
|
||||||
|
mediaPlayer!!.prepare()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Toast.makeText(requireActivity(), R.string.retry, Toast.LENGTH_LONG).show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.tvDelete.visibility = View.GONE
|
||||||
|
binding.ivRecordPlay.visibility = View.GONE
|
||||||
|
binding.llRetryOrComplete.visibility = View.GONE
|
||||||
|
binding.ivRecordPause.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun stopPlaying() {
|
||||||
|
releaseMediaPlayer()
|
||||||
|
stopCountDownTimer()
|
||||||
|
|
||||||
|
binding.tvDelete.visibility = View.VISIBLE
|
||||||
|
binding.ivRecordPlay.visibility = View.VISIBLE
|
||||||
|
binding.llRetryOrComplete.visibility = View.VISIBLE
|
||||||
|
binding.ivRecordPause.visibility = View.GONE
|
||||||
|
binding.soundVisualizer.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun releaseMediaPlayer() {
|
||||||
|
if (mediaPlayer != null) {
|
||||||
|
mediaPlayer!!.release()
|
||||||
|
mediaPlayer = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startCountDownTimer() {
|
||||||
|
countDownTimer = object : CountDownTimer(Long.MAX_VALUE, 1000) {
|
||||||
|
override fun onTick(p0: Long) {
|
||||||
|
second += 1
|
||||||
|
binding.tvTimer.text = recordingTime()
|
||||||
|
|
||||||
|
if (second >= 180) {
|
||||||
|
stopRecording()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFinish() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
countDownTimer!!.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun recordingTime(): String {
|
||||||
|
if (second == 60) {
|
||||||
|
minute += 1
|
||||||
|
second = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minute == 60) {
|
||||||
|
hour += 1
|
||||||
|
minute = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.format(Locale.getDefault(), "%02d:%02d:%02d", hour, minute, second)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
private fun stopCountDownTimer() {
|
||||||
|
if (countDownTimer != null) {
|
||||||
|
countDownTimer!!.cancel()
|
||||||
|
countDownTimer = null
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.tvTimer.text = "00:00:00"
|
||||||
|
second = -1
|
||||||
|
minute = 0
|
||||||
|
hour = 0
|
||||||
|
}
|
||||||
|
}
|
|
@ -94,6 +94,63 @@
|
||||||
android:textSize="13.3sp" />
|
android:textSize="13.3sp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/ll_record_audio"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="13.3dp"
|
||||||
|
android:fontFamily="@font/gmarket_sans_bold"
|
||||||
|
android:text="오디오 녹음"
|
||||||
|
android:textColor="@color/color_eeeeee"
|
||||||
|
android:textSize="16.7sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_record_audio"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="13.3dp"
|
||||||
|
android:layout_marginTop="13.3dp"
|
||||||
|
android:background="@drawable/bg_round_corner_5_3_13181b_3bb9f1"
|
||||||
|
android:fontFamily="@font/gmarket_sans_medium"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingVertical="8dp"
|
||||||
|
android:text="녹음"
|
||||||
|
android:textColor="@color/color_80d8ff"
|
||||||
|
android:textSize="16.7sp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:layout_marginTop="13.3dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/gmarket_sans_medium"
|
||||||
|
android:text="※ "
|
||||||
|
android:textColor="@color/color_777777"
|
||||||
|
android:textSize="13.3sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/gmarket_sans_medium"
|
||||||
|
android:text="오디오 녹음은 최대 3분입니다"
|
||||||
|
android:textColor="@color/color_777777"
|
||||||
|
android:textSize="13.3sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/color_222222">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/gmarket_sans_bold"
|
||||||
|
android:paddingHorizontal="26.7dp"
|
||||||
|
android:paddingTop="26.7dp"
|
||||||
|
android:text="음성녹음"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="18.3sp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_close"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
android:paddingHorizontal="26.7dp"
|
||||||
|
android:paddingTop="26.7dp"
|
||||||
|
android:src="@drawable/ic_close_white"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="81dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/iv_close">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_timer"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/gmarket_sans_light"
|
||||||
|
android:text="00:00:00"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="33.3sp" />
|
||||||
|
|
||||||
|
<com.gauravk.audiovisualizer.visualizer.WaveVisualizer
|
||||||
|
android:id="@+id/sound_visualizer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="120dp"
|
||||||
|
android:layout_marginHorizontal="13.3dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:avColor="@color/av_deep_orange"
|
||||||
|
app:avDensity="0.8"
|
||||||
|
app:avSpeed="normal"
|
||||||
|
app:avType="fill" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_record_start"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginVertical="52.3dp"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
android:src="@drawable/ic_record" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_record_stop"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginVertical="52.3dp"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
android:src="@drawable/ic_record_stop"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/rl_record_play"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_record_play"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:layout_marginTop="90dp"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
android:src="@drawable/ic_record_play" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_record_pause"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:layout_marginTop="90dp"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
android:src="@drawable/ic_record_pause"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_delete"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_marginStart="60dp"
|
||||||
|
android:layout_toEndOf="@+id/iv_record_play"
|
||||||
|
android:fontFamily="@font/gmarket_sans_medium"
|
||||||
|
android:text="삭제"
|
||||||
|
android:textColor="@color/color_bbbbbb"
|
||||||
|
android:textSize="15.3sp" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/ll_retry_or_complete"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="13.3dp"
|
||||||
|
android:layout_marginTop="26.7dp"
|
||||||
|
android:layout_marginBottom="13.3dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_retry_record"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/bg_round_corner_10_13181b_3bb9f1"
|
||||||
|
android:fontFamily="@font/gmarket_sans_bold"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="다시 녹음"
|
||||||
|
android:textColor="@color/color_3bb9f1"
|
||||||
|
android:textSize="18.3sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_complete"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_marginStart="13.3dp"
|
||||||
|
android:layout_weight="2"
|
||||||
|
android:background="@drawable/bg_round_corner_10_3bb9f1"
|
||||||
|
android:fontFamily="@font/gmarket_sans_bold"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="녹음 완료"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="18.3sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
Loading…
Reference in New Issue