전자액자 만들기 (2) - 액티비티 생명주기
2022. 12. 16. 14:04ㆍAndroid
이번에는 사진을 가지고 화면을보여주기때문에 Activtiy랑 레이아웃을 하나더만들어보겟습니다.
- PhotoFrameActivity.kt
package com.example.actionmovie
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
class PhotoFrameActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_photoframe)
}
}
메인액티비에 만들어준다. onCreate함수를 실행하려면 레이아웃도만들어줘야하고 매니페스트에도 이름을 추가해줘야한다.
- AndroidManifest.xml
<activity android:name=".PhotoFrameActivity"/>
- layout -> new -> Layout Resource File 에 <파일이름: activity_photoframe 만들자.>
- activity_photoframe.xml
<?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">
</androidx.constraintlayout.widget.ConstraintLayout>
- PhotoFrameActivity 레이아웃
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/backgroundPhotoImageView"
android:background="@color/black"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:scaleType="center"
app:layout_constraintTop_toTopOf="parent"/>
<ImageView
android:id="@+id/photoImageView"
android:background="@color/black"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:scaleType="center"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
- MainPhotoFrameActivity.kt
package com.example.actionmovie
import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.ImageView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import com.example.actionmovie.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val addphotoButton: Button by lazy {
binding.addPhotoButton
}
private val startphotoFrameModeButton: Button by lazy {
binding.startPhotoFrameModeButton
}
private val imageViewList: List<ImageView> by lazy {
mutableListOf<ImageView>().apply {
add(binding.imageView11)
add(binding.imageView12)
add(binding.imageView13)
add(binding.imageView21)
add(binding.imageView22)
add(binding.imageView23)
}
}
private val imageUriList: MutableList<Uri> = mutableListOf()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
initaddPhotoButton()
initstartPhotoFrameModeButton()
}
private fun initaddPhotoButton() {
binding.addPhotoButton.setOnClickListener {
binding.addPhotoButton.text = "사진이 추가되엇습니다!"
when {
//todo 파일 접근권한이 부여됫는지 확인하고 사진을 선택하는 기능
ContextCompat.checkSelfPermission(
this,
android.Manifest.permission.READ_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_GRANTED -> {
navigatePhotos()
}
//todo 권한을 명시적으로 거부한 경우 나 처음보거나 다시 묻지 않음을 선택한 경우
shouldShowRequestPermissionRationale(
android.Manifest.permission.READ_EXTERNAL_STORAGE
) -> {
//todo 팝업 확인 후 권한 팝업을 띄우는 기능
showPermissionContextPopup()
}
else -> {
//todo 처음 봣을때 띄워주는 코드
requestPermissions(
arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE),
1000
)
}
}
}
}
private fun initstartPhotoFrameModeButton() {
binding.startPhotoFrameModeButton.setOnClickListener {
binding.startPhotoFrameModeButton.text = "전자액자가 실행되엇습니다."
val intent = Intent(this, PhotoFrameActivity::class.java)
imageUriList.forEachIndexed { index, uri ->
intent.putExtra("photo$index", uri.toString())
}
intent.putExtra("photoListSize", imageUriList.size)
startActivity(intent)
}
}
//todo 권한을 허락하거나 거부햇을때 코드를 구현
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray,
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
1000 -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//todo 권한이 잘부여된것
navigatePhotos()
}
}
}
}
private fun navigatePhotos() {
//사진 목록 출력
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "image/*"
startActivityForResult(intent, 2000)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode != Activity.RESULT_OK) {
Toast.makeText(this,"잘못된 접근입니다.",Toast.LENGTH_SHORT).show()
return
}
when (requestCode) {
2000 -> {
val selectedImageUri: Uri? = data?.data
if (selectedImageUri != null) {
if (imageUriList.size == 6) {
Toast.makeText(this, "이미 사진이 꽉 찻습니다.", Toast.LENGTH_SHORT).show()
return
}
imageUriList.add(selectedImageUri)
imageViewList[imageUriList.size - 1].setImageURI(selectedImageUri)
}
}
}
}
private fun showPermissionContextPopup() {
AlertDialog.Builder(this)
.setTitle("권한이 필요합니다")
.setMessage("전자액자에 앱에서 사진을 불러오기 위해 권한이 필요합니다")
.setPositiveButton("동의하기") { _, _ ->
requestPermissions(arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE), 1000)
}
.setNegativeButton("취소하기") { _, _ -> }
.create()
.show()
}
}
- timer함수를이용
- 5초마다 사진이 바뀌는걸볼수잇다.
timer(period = 5 * 1000)
- 액티비티 생명주기를 마지막으로 완성도를 높이도록하겟습니다.
- 사진을추가하고 전자액자실행버튼을누르면 OnCreate -> OnStart -> OnResume첫 화면실행시 호출됨.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_photoframe)
Log.d("PhotoFrame", "OnCreate!!")
override fun onStart() {
super.onStart()
Log.d("PhotoFrame", "OnStart!! timer start")
startTimer()
override fun onResume() {
super.onResume()
Log.d("PhotoFrame", "OnResume!! timer start
override fun onPause() {
super.onPause()
Log.d("PhotoFrame", "OnPause!! timer Pause")
timer?.cancel()
}
override fun onStop() {
super.onStop()
Log.d("PhotoFrame", "OnStop!! timer cancel")
timer?.cancel()
}
override fun onDestroy() {
super.onDestroy()
Log.d("PhotoFrame", "OnDestroy!! 앱이 종료되었습니다")
timer?.cancel()
}
}
- 백그라운드시 OnPasue -> Onstop 순으로 함수가호출되고. 다시 앱을 실행하면 OnResume OnStart함수가 호출됨
- 앱을 종료시키면 OnStop -> OnDestroy 함수가호출됩니다.
- 전체코드
package com.example.actionmovie
import android.icu.text.Transliterator.Position
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import com.example.actionmovie.databinding.ActivityMainBinding
import com.example.actionmovie.databinding.ActivityPhotoframeBinding
import java.util.Timer
import kotlin.concurrent.timer
class PhotoFrameActivity : AppCompatActivity() {
private var mainBinding: ActivityPhotoframeBinding? = null
private val binding get() = mainBinding!!
private val photoList = mutableListOf<Uri>()
private var Position = 0
private var timer: Timer? = null
private val photoImageView: ImageView by lazy {
binding.photoImageView
}
private val backgroundPhotoImageView: ImageView by lazy {
binding.backgroundPhotoImageView
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mainBinding = ActivityPhotoframeBinding.inflate(layoutInflater)
setContentView(binding.root)
Log.d("PhotoFrame", "OnCreate!!")
getphotoUriFromIntent()
}
private fun getphotoUriFromIntent() {
val size = intent.getIntExtra("photoListSize", 0)
for (i in 0..size) {
intent.getStringExtra("photo$i")?.let {
photoList.add(Uri.parse(it))
}
}
}
private fun startTimer() {
timer = timer(period = 5 * 1000) {
runOnUiThread {
Log.d("PhotoFrame", "5초가지나감!!!!!!")
val current = Position
val next = if (photoList.size <= Position + 1) 0 else Position + 1
binding.backgroundPhotoImageView.setImageURI(photoList[current])
binding.photoImageView.alpha = 0f
binding.photoImageView.setImageURI(photoList[next])
binding.photoImageView.animate().alpha(1.0f).setDuration(1000).start()
Position = next
}
}
}
// 액티비티 생명주기
override fun onStop() {
super.onStop()
Log.d("PhotoFrame", "OnStop!! timer cancel")
timer?.cancel()
}
override fun onStart() {
super.onStart()
Log.d("PhotoFrame", "OnStart!! timer start")
startTimer()
}
override fun onResume() {
super.onResume()
Log.d("PhotoFrame", "OnResume!! timer start")
startTimer()
}
override fun onDestroy() {
super.onDestroy()
Log.d("PhotoFrame", "OnDestroy!! 앱이 종료되었습니다")
timer?.cancel()
}
}
- 결과화면
'Android' 카테고리의 다른 글
중고 거래 앱 만들기 (1) - 프래그먼트 (액티비티처럼 동작하는 뷰) (0) | 2022.12.29 |
---|---|
도서리뷰 앱 만들기(2) - 도서리뷰저장하기 (0) | 2022.12.23 |
도서리뷰 앱 만들기 (1) - Open Api 통해 도서목록 가져오기 (0) | 2022.12.21 |
<전자액자 앱만들기>파일 접근 권한과 이미지 업로드 이해와 사용 (0) | 2022.12.13 |
전자액자 앱만들기(1) (0) | 2022.12.13 |