-
TECHIT 앱 스쿨 2기: Android 29일차 (23.06.08)[THEC!T] 앱 스쿨2기 : Android 2023. 6. 8. 21:33728x90
자료 출처 : 안드로이드 앱스쿨 2기 윤재성 강사님 수업 내용
오늘은 어제 내주신 과제에 대한 실습으로 시작을 하였습니다.
ConstraintLayOut 에서 버튼 배치, 텍스트뷰, 에디트텍스트 배치를 하는 문제였습니다.
강사님께서 작성하신 xml 파일과 제가 작성한 xml 파일에서의 차이점은 margin 차이와 padding 차이를 제외하고는 없었습니다.
하기는 제가 작성한 xml 파일 입니다.
<?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" android:padding="5dp" tools:context=".MainActivity"> <LinearLayout android:id="@+id/linearLayout" android:layout_width="match_parent" android:layout_height="60dp" android:orientation="horizontal" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <Button android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:text="Button" /> <Button android:id="@+id/button4" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:text="Button" /> <Button android:id="@+id/button5" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:text="Button" /> </LinearLayout> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:text="TextView" android:textAppearance="@style/TextAppearance.AppCompat.Large" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/linearLayout" /> <EditText android:id="@+id/editTextText" android:layout_width="0dp" android:layout_height="wrap_content" android:ems="10" android:inputType="text" android:text="Name" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:text="TextView" android:textAppearance="@style/TextAppearance.AppCompat.Large" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/editTextText" /> <EditText android:id="@+id/editTextText2" android:layout_width="0dp" android:layout_height="wrap_content" android:ems="10" android:inputType="text" android:text="Name" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView2" /> <Button android:id="@+id/button6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:text="Button" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@+id/editTextText2" /> <Button android:id="@+id/button7" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:text="Button" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/button6" /> <Button android:id="@+id/button8" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:text="Button" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@+id/button7" /> <Button android:id="@+id/button9" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:text="Button" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/button8" /> <Button android:id="@+id/button10" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="158dp" android:layout_marginTop="20dp" android:layout_marginEnd="158dp" android:text="Button" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/button9" /> </androidx.constraintlayout.widget.ConstraintLayout>
이후로는 Space에 대하여 설명해주셨습니다.
Space는 Layout는 아니지만 Layout을 이용하여 화면을 구성할 때 보조 수단으로 사용하는 view이며, 화면 구성 시 여백이 필요할 경우 사용한다고 하셨습니다.
Space에 대한 설명 이후 에는 Space와 margin 에 대하여 실습을 진행하였습니다.
첫 번째 버튼 marginLeft를 50dp 설정
두 번째 버튼 marginTop를 50dp 설정
세 번째 버튼 Space를 50dp 설정
다음으로는 IncludeOtherLayout 에 대한 설명을 해주셨습니다.
Layout 에서 다른 Layout 을 포함 시킬 수 있으며, 다수의 화면을 구성할 때 중복되는 부분이 있을 경우 사용한다고 하셨습니다. 그리고 화면에 보인다는 것은 이미 객체가 생성되었다는 뜻 이므로 해당 레이아웃에 접근 할 때는 id를 지정하여 접근 하는 방식을 사용한다고 말씀해 주셨습니다.
다음으로는 TextView 에 대해서 설명해주셨습니다.
TextView의 주요 속성
text : 표시할 문자열을 설정
textAppearance : 미리 설정되어 있는 문자열 관련 셋팅
fontFamily : 폰트. 코드를 통해 설정하는 것을 권장(한글 때문에...)
typeface : 폰트에서 지원을 한다면, serif, monospace 등을 설정할 수 있다.
textSize : sp 단위의 글자 수 -> 프린트로 뽑았을 때의 글자크기 단위
lineSpacingExtra : 라인 간격
textColor : 글자 색상
textStyle : 볼드, 이탤릭, 모두 대문자 설정
textAlignment : 정렬
alpha : 투명도
lines : 최대 줄 수. 생략하면 무한대로 설정된다.코드에서 텍스트 뷰에 글자를 설정할 때
textView.text = "기존 문자열"
textView.text = "새로운 문자열"
이렇게 코드를 작성할 경우 textView 에는 글자가 덮어씌워 집니다.
즉 text가 완전히 변경됩니다.
하지만 기존내용을 유지하면서 text를 추가 하고 싶을 경우 append() 를 사용하여 text를 추가 할 수 있습니다.
만약 줄 바꿈을 하고 싶다면
append("추가하는 문자열 \n")
\n 을 이용하여 줄 바꿈을 할 수 있습니다.
다음은 버튼에 대해서 설명해주셨습니다.
Button에 대한 설명
text : 표시할 문자열
ImageButton
srcCompat : 표시할 이미지
이미지 버튼을 사용할 때는 background 색상에 투명도를 0으로 설정해서 사용class MainActivity : AppCompatActivity() { lateinit var activitymainBinding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) activitymainBinding = ActivityMainBinding.inflate(layoutInflater) setContentView(activitymainBinding.root) activitymainBinding.run { button2.run{ // 버튼의 문자열을 변경한다. text = "버튼 입니다." // 버튼을 눌렀을 때 반응하는 리스너 setOnClickListener { activitymainBinding.textView.text = "버튼을 눌렀습니다." } } imageButton2.run{ // 이미지 버튼의 이미지를 변경한다. setImageResource(R.drawable.imgflag8) // 이미지 버튼을 눌렀을 때 반응하는 리스너 setOnClickListener{ activitymainBinding.textView.text = "이미지 버튼을 눌렀습니다." } } } } }
다음으로는 에디트텍스트, 포커스, thread, 키보드 올리기 & 내리기 등을 실습을 통하여 학습하였습니다.
EditText
사용자에게 문자열 데이터를 입력을 받을 때 사용하는 View
text : EditText에 표시할 문자열을 설정한다.
hint : 입력된 값이 없을 경우 표시할 안내 문구를 설정한다.
inputType : 입력 값에 대해 설정한다. 표시되는 형식, 나타나는 키보드 등에 영향을 준다.
imeOptions : 나타나는 키보드의 Enter 키 모양을 설정한다.EditText의 메서드
TextWatcher : 사용자가 입력한 내용을 실시간으로 감시한다.
// 입력 감시자 설정 val editTextWatcher1 = EditTextWatcher1() addTextChangedListener(editTextWatcher1) // EditText 입력 감시자 inner class EditTextWatcher1 : TextWatcher { // 입력 내용 변경 전 override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { activityMainBinding.textView.text = "before : ${s}" } // 입력 내용 변경 했을 때 override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { activityMainBinding.textView2.text = "changed : ${s}" } // 입력 내용이 변경된 후 override fun afterTextChanged(s: Editable?) { activityMainBinding.textView3.text = "after : ${s}" } }
editTextTextPassword.run{ // addTextChangedListener 를 사용할 때 고차함수를 사용하면 // TextWatcher의 after 역할을 수행한다. // 즉 실시간으로 사용자의 입력 내용을 받아 낼 수 있다. addTextChangedListener { textView.text = it } }
EditorAction : 키보드의 Enter 키를 눌렀을 때 발생하는 이벤트editTextText.run { // 엔터키를 눌렀을 때의 이벤트 setOnEditorActionListener { v, actionId, event -> textView.text = "엔터 버튼을 눌렀습니다." textView2.text= text.toString() // true를 반환하면 엔터키 누른 후에 포커스가 현재 EditText로 유지된다. // false를 반환하면 엔터키 누른 후에 다음 EditText로 포커스가 이동한다. false } }
포커스 : 입력하려는 위치, 쉽게 비유하자면 글 작성 시 | <- 이 모양이 깜빡 거리는 곳.
뷰 내부 코드에서 requestFocus() 를 작성하면 해당 EditText에 포커스를 준다.
만약 다른 뷰로 포커스를 이동 시키고 싶을 때는 다른 뷰이름.requestFocus() 으로 작성하면 포커스가 이동된다.
이후로는 LogCat 에 대해서 설명해주셨습니다.
LogCat : 안드로이드 스튜디오에서 에뮬레이터나 단말기에서 사용하는 콘솔
// information, 정보를 출력하는 용도로 사용한다. Log.i("테스트", "반갑습니다.") // debug, 개발중에 출력해보고 싶은 것을 있을 때 사용한다. Log.d("테스트", "aaa") // error, 오류 메세지를 출력해보고 싶을 때 사용한다. Log.e("테스트", "bbb") // warning, 경고 메시지를 출력해보고 싶을 때 사용한다. Log.w("테스트", "ccc") // verbose, 기타 용도로 사용한다. Log.v("테스트", "ddd")
마지막으로는 이제 오늘 알려주신 개념과 방법들을 바탕으로 문제를 작성하였습니다.
강사님께서 조건으로 주시지는 않았지만 개인적으로 포커스와 키보드 등을 올리고 내리는 것 까지 추가해봤습니다.
첫 번째 문제 구구단 출력
package com.test.android14_ex01 import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.os.SystemClock import android.view.inputmethod.InputMethodManager import com.test.android14_ex01.databinding.ActivityMainBinding import kotlin.concurrent.thread class MainActivity : AppCompatActivity() { lateinit var activityMainBinding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) activityMainBinding = ActivityMainBinding.inflate(layoutInflater) setContentView(activityMainBinding.root) activityMainBinding.run{ thread { SystemClock.sleep(500) val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager imm.showSoftInput(currentFocus, 0) } editTextNumber.run{ // 포커스를 가져온다. requestFocus() // 엔터키를 눌렀을 경우 setOnEditorActionListener { v, actionId, event -> val num = text.toString().toInt() // 기존에 있는 텍스트를 정리한다. textView.text = "" for(i in 1 .. 9){ textView.append("$num X $i = ${num*i}\n") } focusUnlock() false } } button.run{ setOnClickListener { val num = editTextNumber.text.toString().toInt() // 기존에 있는 텍스트를 정리한다. textView.text = "" for(i in 1 .. 9){ textView.append("$num X $i = ${num*i}\n") } focusUnlock() } } } } // 포커스 해제 함수 fun focusUnlock(){ SystemClock.sleep(10) // 포커스를 해제한다. val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager if(currentFocus != null){ imm.hideSoftInputFromWindow(currentFocus!!.windowToken,0) currentFocus!!.clearFocus() } } }
두 번째 문제 사칙연산 계산기 작성
package com.test.android14_ex02 import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.os.SystemClock import android.view.inputmethod.InputMethodManager import com.test.android14_ex02.databinding.ActivityMainBinding import kotlin.concurrent.thread class MainActivity : AppCompatActivity() { lateinit var activityMainBinding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) activityMainBinding = ActivityMainBinding.inflate(layoutInflater) setContentView(activityMainBinding.root) activityMainBinding.run{ thread { SystemClock.sleep(500) val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager imm.showSoftInput(currentFocus,0) } editTextNumber.run{ requestFocus() setOnEditorActionListener { v, actionId, event -> false } } editTextNumber2.run{ setOnEditorActionListener { v, actionId, event -> val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager if(currentFocus != null){ imm.hideSoftInputFromWindow(windowToken,0) currentFocus!!.clearFocus() } true } } button.run { setOnClickListener { textViewUpdate("+") } } button2.run { setOnClickListener { textViewUpdate("-") } } button3.run { setOnClickListener { textViewUpdate("*") } } button4.run { setOnClickListener { textViewUpdate("/") } } } } fun textViewUpdate(oper: String) { when(oper){ "+" -> activityMainBinding.run{ val num1 = editTextNumber.text.toString().toInt() val num2 = editTextNumber2.text.toString().toInt() textView.text = "$num1 + $num2 = ${num1 + num2}" } "-" -> activityMainBinding.run{ val num1 = editTextNumber.text.toString().toInt() val num2 = editTextNumber2.text.toString().toInt() textView.text = "$num1 - $num2 = ${num1 - num2}" } "*" -> activityMainBinding.run{ val num1 = editTextNumber.text.toString().toInt() val num2 = editTextNumber2.text.toString().toInt() textView.text = "$num1 * $num2 = ${num1 * num2}" } "/" -> activityMainBinding.run{ val num1 = editTextNumber.text.toString().toInt() val num2 = editTextNumber2.text.toString().toInt() textView.text = "$num1 / $num2 = ${num1 / num2}" } else -> return } } }
마지막 문제는 입력 받은 것을 저장하고 버튼을 누르면 정보를 Logcat에 출력하는 문제였습니다.
포커스의 이동, 키보드 등 조건 등이 추가로 있는 문제였습니다.
시작화면
수학 점수까지 모두 입력 후 키보드의 엔터를 누른 경우
모든 텍스트는 지워지고 내부적으로 저장한다.
키보드를 내리면 현재 저장된 학생의 수를 알 수가 있다.
버튼을 누르면 Logcat 에서 학생의 정보를 출력한다.
확인을 위하여 상기 사진에서 추가하여 하기 사진에서 학생의 정보를 총 3명 입력하였습니다.
package com.test.android14_ex03 import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.os.SystemClock import android.util.Log import android.view.inputmethod.InputMethodManager import com.test.android14_ex03.databinding.ActivityMainBinding import kotlin.concurrent.thread data class Student(val name:String, val age: Int, val kor:Int, val eng:Int, val math:Int){ fun printInfo(): String{ return "이름 : $name \n나이 : $age\n국어점수 : $kor\n영어점수 : $eng\n수학점수 : $math\n " } } class MainActivity : AppCompatActivity() { lateinit var activityMainBinding: ActivityMainBinding val stdList = ArrayList<Student>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) activityMainBinding = ActivityMainBinding.inflate(layoutInflater) setContentView(activityMainBinding.root) activityMainBinding.run{ // 최초 포커스 thread { SystemClock.sleep(500) val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager imm.showSoftInput(currentFocus,0) } stdName.run{ requestFocus() // 엔터키를 누른 경우 setOnEditorActionListener { v, actionId, event -> false } } stdAge.run{ // 엔터키를 누른 경우 setOnEditorActionListener { v, actionId, event -> false } } korSco.run{ // 엔터키를 누른 경우 setOnEditorActionListener { v, actionId, event -> false } } engSco.run{ // 엔터키를 누른 경우 setOnEditorActionListener { v, actionId, event -> false } } mathSco.run{ // 엔터키를 누른 경우 setOnEditorActionListener { v, actionId, event -> // 입력받은 학생의 정보를 리스트에 저장 val name = stdName.text.toString() stdName.text.clear() val age = stdAge.text.toString().toInt() stdAge.text.clear() val kor = korSco.text.toString().toInt() korSco.text.clear() val eng = engSco.text.toString().toInt() engSco.text.clear() val math = mathSco.text.toString().toInt() mathSco.text.clear() stdList.add(Student(name, age, kor, eng, math)) // 저장된 학생 수 변경 stdCount.text = "현재 저장된 학생 정보 : ${stdList.size}" // 포커스 정보 넘김 stdName.requestFocus() false } logBtn.run{ setOnClickListener { var korTotal = 0 var engTotal = 0 var mathTotal = 0 for(std in stdList){ Log.i("studentInfo",std.printInfo()) korTotal += std.kor engTotal += std.eng mathTotal += std.math } Log.i("studentInfo","국어 총점 : $korTotal") Log.i("studentInfo","영어 총점 : $engTotal") Log.i("studentInfo","수학 총점 : $mathTotal\n ") Log.i("studentInfo","국어 평균 : ${korTotal/stdList.size}") Log.i("studentInfo","영어 평균 : ${engTotal/stdList.size}") Log.i("studentInfo","수학 평균 : ${mathTotal/stdList.size}") // 포커스 정보 넘김 stdName.requestFocus() // 키보드 올림 val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager imm.showSoftInput(currentFocus,0) } } } } } }
마무리
마지막 문제를 작성하면서 뭔가 코드의 중복되는 부분들이 보여 중복 제거를 해보려고 하였으나 실력이 부족하여 잘되지 않았습니다. 내일 강사님께서 작성하시는 코드를 보면서 생각을 해봐야 할 것 같습니다. 그리고 혼자 독학을 하는 것이 아니라서 그런가 배우는데에 있어 아직까지는 재미가 있었습니다~!
오늘의 마음가짐
배우는 것을 즐기는 사람이 되자~!
'[THEC!T] 앱 스쿨2기 : Android' 카테고리의 다른 글
TECHIT 앱 스쿨 2기: Android 31일차 (23.06.12) (1) 2023.06.12 TECHIT 앱 스쿨 2기: Android 30일차 (23.06.09) (1) 2023.06.10 TECHIT 앱 스쿨 2기: Android 28일차 (23.06.07) (0) 2023.06.07 TECHIT 앱 스쿨 2기: Android 27일차 (23.06.02) (0) 2023.06.03 TECHIT 앱 스쿨 2기: Android 26일차 (23.06.01) (0) 2023.06.01