반응형
버튼 누르면 이미지 변경
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var rollBtn: Button = findViewById(R.id.roll)
rollBtn.setOnClickListener{
var myDice:Dice = Dice()
var num = myDice.roll()
// var textview: TextView = findViewById(R.id.number)
// textview.text = num.toString()
var diceImg: ImageView = findViewById(R.id.diceimg)
when(num) {
1 -> diceImg.setImageResource(R.drawable.dice_1)
2 -> diceImg.setImageResource(R.drawable.dice_2)
3 -> diceImg.setImageResource(R.drawable.dice_3)
4 -> diceImg.setImageResource(R.drawable.dice_4)
5 -> diceImg.setImageResource(R.drawable.dice_5)
6 -> diceImg.setImageResource(R.drawable.dice_6)
}
}
}
}
class Dice {
fun roll():Int {
return (1..6).random()
}
}
- 버튼 누를 때마다 1~6 사이의 랜덤 값을 받아와서 값에 맞게 주사위 이미지 변경하는 예제
ListView
- 뷰 안에서 리스트로 표현하는 레이아웃
- 만들려고하는 리스트 갯수 만큼 미리 할당 - 메모리 낭비
RecyclerView 예제
- 롤리팝 버전부터 생성된 뷰로 ListView의 단점을 보완
- itemview가 1000개가 있더라도 화면에 보여줄 수 있는 갯수 + 여유 몇 개만 추가적으로 할당하고 이후 사용자가 스크롤할 때 이전에 한 갯수 만큼 다시 메모리에 넣으면서 기존에 뷰 공간에 새로운 데이터를 넣어 처리한다. (뷰 공간을 재활용 하여 새로운 데이터를 넣는 레이아웃)
- 리스트 안에 텍스트, 이미지 또는 리니어레이아웃, 그리드 등 확장하기 용이
- 화면에 보여질 수 있는 리스트 갯수에 위에서 사라지는 리스트 갯수만큼만 할당
- 구조
- layout : activity_main.xml, item_list.xml (itemView 들의 집합)
- code : MainActivity.kt - recyclerview 와 adapter를 결합
- data 클래스 : Affirmation
- 컴파일 한 객체(itemview)를 Adapter에서 받은 후 binding
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
</FrameLayout>
- item을 담을 리사이클러 뷰 코드
list_item
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="194dp"
android:id="@+id/item_image"
android:importantForAccessibility="no"
android:scaleType="centerCrop" />
<TextView
android:id="@+id/item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:textAppearance="@android:style/TextAppearance.Material.Subhead" />
</LinearLayout>
- item을 담을 뷰 레이아웃
- centerCrop : 이미지가 영역보다 클 때 방식 지정
class Affirmation(val strResource:Int, val imageResource:Int) {}
class DataSet {
fun makeSet(): List<Affirmation> {
return listOf<Affirmation>(
Affirmation(R.string.affirmation1, R.drawable.image1),
Affirmation(R.string.affirmation2, R.drawable.image2),
Affirmation(R.string.affirmation3, R.drawable.image3),
Affirmation(R.string.affirmation4, R.drawable.image4),
Affirmation(R.string.affirmation5, R.drawable.image5),
Affirmation(R.string.affirmation6, R.drawable.image6),
Affirmation(R.string.affirmation7, R.drawable.image7),
Affirmation(R.string.affirmation8, R.drawable.image8),
Affirmation(R.string.affirmation9, R.drawable.image9),
Affirmation(R.string.affirmation10, R.drawable.image10)
)
}
}
- DataSet 생성 , Affirmation 클래스는 Int, Int를 매개변수로 받는 클래스
Adapter
- 객체 안에 이미지, 텍스트 등 여러 종류의 데이터(데이터 클래스)를 넣어주는 클래스
- Adapter와 recyclerView를 연결하는 것을 binding(결합) 한다고 한다. 이러한 결합을 MainActivity에서 동작한다.
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.recyclerapp_2.R
import com.example.recyclerapp_2.data.Affirmation
class ItemAdapter(private val context: Context, private val dataset: List<Affirmation>) :
RecyclerView.Adapter<ItemAdapter.ItemViewHolder>() {
class ItemViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
val textview: TextView = view.findViewById(R.id.item_title)
val imageview: ImageView = view.findViewById(R.id.item_image)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
val item_layout = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)
return ItemViewHolder(item_layout)
}
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
val item = dataset[position]
holder.textview.text = context.resources.getString(item.strResource)
holder.imageview.setImageResource(item.imageResource)
}
override fun getItemCount() = dataset.size
}
Layout
- Linear
- 수직 : vertical, 수평 :horizontal 으로 레이아웃 지정
- layout_weight : 가중치 설정 (남는 공간이 있으면 가중치가 있는 뷰가 가진다.)
- gravity : 레이아웃 안 정렬, layout_gravity : 바깥 레이아웃 정렬
- Relative
- 기준인 뷰가 있고 그 뷰와 id를 통해 관련된 레이아웃을 생성 (상대적 배치)
- Frame
- 여러 개 화면이 있는 것처럼 보여주는 레이아웃
- Grid
- 행 또는 열을 기준으로 바둑판 모양의 배치를 정하는 레이아웃
- Constraint
- Coordinate
- Motion
Activity 이동
- A : Running(실행) , B : Paused (상태 유지)
- Stack 처럼 액티비티 위에 쌓이고 끝나면 되돌아온다.
Life Cycle
- start -> finish 관계가 기본
- 액티비티 간에서도 값을 전달 및 받아올 수 있다. 이 데이터를 받는 공간을 bundle 이라고 한다.
- 메인 액티비티는 받아온 값이 어느 레이아웃에서 온 지 알아야 한다. Req.code 라는 상수 값을 하나 정의하여 결과를 보낼 때 데이터와 Req.code를 같이 보내서 구별 한다.
- ActivityResult Launcher를 사용하는 것이 최근 사용 방법
Manifests 설정
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MenuActivity"></activity>
- 액티비티가 여러 개이므로 manifests에 액티비티를 지정
MainActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button: Button = findViewById(R.id.button)
button.setOnClickListener{
val intent: Intent = Intent(applicationContext, MenuActivity::class.java)
startActivity(intent)
}
}
}
- Intent : 할 일 (Intent(현재 위치, 이동할 위치))
finish
class MenuActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_menu)
val button: Button = findViewById(R.id.button)
button.setOnClickListener{
finish()
}
}
}
- finish() : 이전 위치로 되돌아 간다.
Bundle
- 예전 방식
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button: Button = findViewById(R.id.button)
button.setOnClickListener{
val intent: Intent = Intent(applicationContext, MenuActivity::class.java)
intent.putExtra("age", 23)
startActivityForResult(intent, REQ_CODE)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQ_CODE && resultCode == RESULT_OK) {
val name: TextView = findViewById(R.id.name)
name.text = data!!.getStringExtra("name")
}
}
companion object {
const val REQ_CODE = 10
}
}
class MenuActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_menu)
val bundle:Bundle? = intent.extras // 데이터 받아 오기
val age: Int? = bundle?.getInt("age") //받을 데이터의 키
val button: Button = findViewById(R.id.button)
button.setOnClickListener{
val ret = Intent()
ret.putExtra("name", "Mike : "+ age )
setResult(RESULT_OK, ret)
finish()
}
}
}
ActivityResultLauncher
class MainActivity : AppCompatActivity() {
private lateinit var launcher: ActivityResultLauncher<Intent>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
result: ActivityResult -> if (result.resultCode == RESULT_OK) {
val name: TextView = findViewById(R.id.name)
name.text = result.data!!.getStringExtra("name")
}
}
val button: Button = findViewById(R.id.button)
button.setOnClickListener{
val intent: Intent = Intent(applicationContext, MenuActivity::class.java)
intent.putExtra("age", 23)
//startActivityForResult(intent, REQ_CODE)
launcher.launch(intent)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
}
companion object {
const val REQ_CODE = 10
}
}
Intent
- 안드로이드에서 Component는 Activity, Service, BroadcastReceiver, Content Provider 로 4개라고 볼 수 있다.
- 여러 액티비티가 있을 때 Main 은 직접 이동시키는 것이 아니라 Android 시스템에 요청을 해서 이동을 한다. 이와 같은 의사표시를 할때 사용하는 것을 Intent (할 일)라고 한다. Intent에는 명시적 인텐트 , 묵시적 인텐트가 있다.
- 명시적 인텐트 : Intent(.Activity , Secend::class.java)
- 묵시적 인텐트 : Intent(aoc.VIEW Browsable)
Activity Life Cycle
- 안드로이드 시스템이 자동으로 적용해주는 시스템
- 실행 (활성화) 메서드
- onCreate(액티비티가 object로 생성이 될때 레이아웃과 연결)
- onStart, onResume(다시 실행)
- 멈춤 (액티비티의 변경)
- onPause(일부분이 보일 때), onStop (완전히 가려서 안보일 때)
- 소멸 (비활성화)
- onDestroy : onStop 상태인 액티비티를 비활성화 시킬 때 사용
- A(메인) , B, C 액티비티가 있을 때
- A.onCreate(), A.onStart(), A.Resume()이 스택 구조로 실행
- B 액티비티로 이동했을 때 : A.onCreate(), A.onStart(), A.onResume(), A.onPause(), B.onCreate~ B.onResume() 순으로 쌓인다. 현재 액티비티의 상해는 A: Paused, B: Resumed
- B 액티비티에서 C로 이동했을 때 : A,B 는 Stopped, C는 Resumed 상태
- C 액티비티를 Finish() 했을 때 : A는 Stopped, B는 Paused, C는 Resumed 상태
- B 액티비티를 Finish() 했을 때 : A는 Resumed, B는 Paused, C는 Destroyed 상태
- A에서 또 다른 액티비티를 눌렀을 때 : A는 Resumed, B,C는 Destroyed 상태
Broadcast Receiver
- 방송 수신기 = 시스템 이벤트 전달
- 사용 방법
- Manifest 등록
- Code 상에서 동적으로 등록 - Receiver Class 정의 또는 Receiver Object 정의
buildFeatures {
viewBinding = true
}
- viewBinding을 위한 build.gradle 에 객체 지정 (ActivityMainBinding 생성)
반응형