kotlinで画像と音声を用いたアニメーション作成アプリを作ろうとしています。
イメージとしてはプレゼンテーションの簡易版で、画像を挿入し、音声を入れ、4つを組み合わせ動画にしたいと考えています。
現状画像挿入と音声はネットにあったものを参考に一つのアプリとして作りました。
しかし、これらを4つ並べる方法がわかりません。
スクロールが必要なので、scrollviewを使おうとしましたが、同じidになってしまいここから進めずにいます。
また、recycler viewで繰り返す方法も調べてみましたがネットには同じものを繰り返すものが見つからず、こちらも進められずにいます。
どのようなレイアウトで作成していくのが良いのか、お力添えよろしくお願いいたします。
絵コンテを雑ながら追加してみました。
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".SecondActivity"> <LinearLayout android:id="@+id/linearLayout3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"> <Button android:id="@+id/record" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="50dp" android:layout_marginRight="50dp" android:text="録音" android:textSize="20sp" /> <Button android:id="@+id/stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="50dp" android:layout_marginRight="50dp" android:text="停止" android:textSize="20sp" /> <Button android:id="@+id/playback" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="50dp" android:layout_marginRight="50dp" android:text="再生" android:textSize="20sp" /> </LinearLayout> <ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toTopOf="@+id/linearLayout3" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/linearLayout2" tools:srcCompat="@tools:sample/avatars" /> <Button android:id="@+id/picturebutton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="画像を挿入する" app:layout_constraintBottom_toTopOf="@+id/linearLayout3" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/linearLayout2" /> </androidx.constraintlayout.widget.ConstraintLayout>
private const val LOG_TAG = "AudioRecordTest" private const val REQUEST_RECORD_AUDIO_PERMISSION = 200 class SecondActivity : AppCompatActivity() { private var recorder: MediaRecorder? = null private var fileName: String = "" private var player: MediaPlayer? = null private var permissionToRecordAccepted = false private var permissions: Array<String> = arrayOf(Manifest.permission.RECORD_AUDIO) override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) permissionToRecordAccepted = if (requestCode == REQUEST_RECORD_AUDIO_PERMISSION) { grantResults[0] == PackageManager.PERMISSION_GRANTED } else { false } if (!permissionToRecordAccepted) finish() } private fun onRecord(start: Boolean) = if (start) { startRecording() } else { stopRecording() } private fun onPlay(start: Boolean) = if (start) { startPlaying() } else { stopPlaying() } private fun startPlaying() { player = MediaPlayer().apply { try { setDataSource(fileName) prepare() start() } catch (e: IOException) { Log.e(LOG_TAG, "prepare() failed") } } } private fun stopPlaying() { player?.release() player = null } private fun startRecording() { recorder = MediaRecorder().apply { setAudioSource(MediaRecorder.AudioSource.MIC) setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP) setOutputFile(fileName) setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB) try { prepare() } catch (e: IOException) { Log.e(LOG_TAG, "prepare() failed") } start() } } private fun stopRecording() { recorder?.apply { stop() release() } recorder = null } override fun onCreate(savedInstanceState: Bundle?) { fileName = "${externalCacheDir?.absolutePath}/audiorecordtest.3gp" super.onCreate(savedInstanceState) setContentView(R.layout.activity_second2) var pictureButton : Button = findViewById(R.id.picturebutton) pictureButton.setOnClickListener { val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply { addCategory(Intent.CATEGORY_OPENABLE) type = "image/*" } startActivityForResult(intent, READ_REQUEST_CODE) } ActivityCompat.requestPermissions(this, permissions, REQUEST_RECORD_AUDIO_PERMISSION) val record = findViewById<Button>(R.id.record) //録音オブジェクト取得 val stop = findViewById<Button>(R.id.stop) //録音停止オブジェクト取得 val playback = findViewById<Button>(R.id.playback) //再生オブジェクト取得 val listener = RecordButton() //レコードボタンリスナのインスタンス生成 record.setOnClickListener(listener) //レコードボタンリスナの設定 stop.setOnClickListener(listener) playback.setOnClickListener(listener) val btnFinish: Button = findViewById(R.id.btnFinish) btnFinish.setOnClickListener { finish() } } companion object{ private const val READ_REQUEST_CODE: Int = 42 } //クリックイベントの設定 private inner class RecordButton : View.OnClickListener { override fun onClick(v: View?) { Log.i(LOG_TAG, "クリック成功") Log.i(LOG_TAG, fileName) if(v != null){ when(v.id){ //録音開始ボタン R.id.record -> { onRecord(true) Log.i(LOG_TAG, "録音開始") } //録音停止ボタン R.id.stop -> { onRecord(false) Log.i(LOG_TAG, "録音終了") } R.id.playback -> { onPlay(true) Log.i(LOG_TAG, "再生中") } } } } } override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) { super.onActivityResult(requestCode, resultCode, resultData) if (resultCode != RESULT_OK) { return } when (requestCode){ READ_REQUEST_CODE -> { try { resultData?.data?.also { uri -> val inputStream = contentResolver?.openInputStream(uri) val image = BitmapFactory.decodeStream(inputStream) val imageView = findViewById<ImageView>(R.id.imageView) imageView.setImageBitmap(image) } }catch (e: Exception){ Toast.makeText(this, "エラーが発生しました", Toast.LENGTH_LONG).show() } } } } }

回答1件
あなたの回答
tips
プレビュー