⏲️ 공부시간 9 : 00 ~ 10 : 20
29번 문제를 풀었다.
어렵지 않다고 생각했는데 엄청 오래걸려서 풀었다.
이유는 배열을 정리하란 말이 없었는데 내맘대로 배열을 쳐 정리하려고 들었음
처음에 정렬해서 제일 작은수를 지우려고 했는데 거기에 매몰되어버림 ㅋ
문제/나의 풀이과정/다른사람의 풀이과정 링크
https://velog.io/@orinugoori_art/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-CODEKATA-29-%EC%A0%9C%EC%9D%BC-%EC%9E%91%EC%9D%80-%EC%88%98-%EC%A0%9C%EA%B1%B0%ED%95%98%EA%B8%B0-y29r5se0
⏲️ 공부 시간 10 : 30 ~ 12 : 30
정수를 입력해도 무조건 실수로 처리함
Ex) 1+2 를 했는데 3.0 으로 나옴; 꼴뵈기싫다
→ StringAnalyze 에 정수랑 실수를 구분하는 코드를 넣던가 해야할듯?
버튼 누를때 누르는 모션이 없으니까 눌러도 누른거같지가 않게 느껴진다.
→ 버튼누르는 모션을 어떻게 추가하는지 알아봐야 할 듯?
기껏 입체적인 계산기를 그려놨는데 왜 누르질 못하니..
폰트 추가하기
폰트 넣는거 깜박했다. 내일 추가해야지..
일단 폰트 먼저 변경했음
내가 옛날에 구매한 GPZ 비디오 테이프 라는 폰트가 레트로한 느낌이라 잘 어울 릴것 같아서
res 에 font 디렉토리를 생성하고
ttf 파일을 이름을 전부 소문자로 변경해서 넣어줬다.
그리고 적용하고 싶은 텍스트에 fontFamily 속성을 사용해서 폰트를 변경해줬다.
그리고 어제 폰트크기가 너무 큰것 같아서 40 →30 으로 줄여줌
폰트 사이즈를 줄였더니 위치가 애매한 느낌이라 폰트 위치도 변경해줬다.
변경 전후 비교


어제 만든 StringAnalyze 클래스에는 받은 문자열을 실수로만 처리해서 이걸 정수도 처리할 수 있게 만들어줘야함
class StringAnalyze {
fun filterNumbers(currentInput: String): List<Number> {
return currentInput.split("+","-","*","/")
.mapNotNull { it.toDoubleOrNull() ?: it.toIntOrNull() }
}
fun filterOperators(currentInput: String): List<String> {
return currentInput.split(" ")
.filter{it.toDoubleOrNull()==null && it.toIntOrNull() == null }
}
}
두 함수의 반환타입을 에서 로 변환해주고, 정수와 실수를 판단하게했다.
Calculator Class 수정
class Calculator {
fun add(numbers: List<Number>): String {
return if (numbers.isEmpty()) {
"0"
} else {
val sum = numbers.sumOf { it.toDouble() }
if (sum % 1.0 == 0.0) {
sum.toInt().toString()
} else {
sum.toString()
}
}
}
}
Calculator의 함수에서도 List의 타입을 Number 로 변경해줬다.
그랬더니 sum()함수가 적용이 안돼서 찾아보니까
sum은 컬렉션의 모든 요소를 합하는거고, sumOf는 컬렉션의 요소를 내가 지정한 방식으로 변환해서 합하는거라고함.
그래서 sumOf로 만약에 서로 다른 타입의 숫자가 들어와도 같은 타입으로 변환해서 계산을 한 다음에 그 결과값이 Int 인지 Double인지 판별해서 각 타입에 맞게 변환해서 뱉게했다.
어제는 앱을 테스트 해보니까 버튼을 입체적으로 제작해놨는데 누르는 효과가 없으니까 너무 어색하게 느껴졌다. 버튼을 누를때 티가 나게 변경해주고 싶어졌음
일단은 눌렸을 때의 생김새를 만들어줘야한다고해서
테스트용으로 mod 버튼만 만들어봤다.
drawable 폴더에 눌러줄때의 이미지와 평소상태의 이미지를 선택해줄 xml 파일 추가
<?xml version="1.0" encoding="UTF-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/ibtn_pressed_mod"></item>
<item android:state_pressed="false" android:drawable="@drawable/ibtn_mod"></item>
</selector>
나는 pressed_btn.xml 라는 이름의 파일로 만들었고 안에 selector를 사용해서 작성해줬다.
메인 레이아웃에서 mod 버튼의 src 수정
<ImageButton
android:id="@+id/ibtn_mod"
android:layout_width="70dp"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
**android:src="@drawable/pressed_btn"**
android:background="@android:color/transparent"
android:layout_marginTop="40dp"
android:layout_marginStart="50dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/iv_display"
android:contentDescription="%"/>
src 를 그냥 png 파일에서 내가 만든 xml 파일로 지정해준다.
실행해보면 눌렀을 때 이미지가 변경된다.
나머지 소스들을 다 만들어주고 각각 selector file을 만들어서 바꿔줌 개노가다였다.
궁금한점
이렇게 여러개의 버튼을 하나하나 다 selector xml을 작성해야하는건가?
더 효율적으로 처리할 수 있을거같은데 ㅜ 일단은 그냥 노가다로 함
⏲️ 공부시간 12 : 30 ~ 13 : 10
15 : 00 ~ 16 : 10
일단 Calculator 에 빼기, 곱하기, 나누기, 나머지 연산에 대한 함수를 각각 만들었다.
Subtract 빼기 함수
fun subtract(numbers: List<Number>): String {
var calculateNumber = numbers[0].toDouble()
for (i in 1 until numbers.size) {
calculateNumber -= numbers[i].toDouble()
}
return if (calculateNumber % 1.0 == 0.0) {
calculateNumber.toInt().toString()
} else {
calculateNumber.toString()
}
}
calculateNumber 라는 변수에 numbers의 첫번째 요소 즉 앞의 숫자를 Double로 변환해서 넣고,
numbers 다음 요소들을 calculateNumber에서 뺐다. 이렇게하면
3-2를 입력한다고 했을때 numbers에는 [3,2] 가 들어가있기 때문에
인덱스 [0]의 요소인 3에서 인덱스[1]의 요소인 2를 뺄 수있음
그리고 return if 를 사용해서 정수와 실수를 구분해서 내보내줬다.
multiply 곱하기 함수
fun multiply(numbers: List<Number>): String {
var calculateNumber = numbers[0].toDouble()
for (i in 1 until numbers.size) {
calculateNumber *= numbers[i].toDouble()
}
return if (calculateNumber % 1.0 == 0.0) {
calculateNumber.toInt().toString()
} else {
calculateNumber.toString()
}
}
곱하기에도 알아보기 편하게 calculateNumber라는 변수에 numbers의 요소중 첫번째를 넣고
이번에는 곱해줬다.
divide 나누기 함수
fun divide(numbers: List<Number>): String {
var quotient = numbers[0].toDouble()
for (i in 1 until numbers.size) {
quotient /= numbers[i].toDouble()
}
return if (quotient % 1.0 == 0.0) {
quotient.toInt().toString()
} else {
quotient.toString()
}
}
mod 나머지함수
fun mod(numbers: List<Number>): String {
var calculateNumber = numbers[0].toDouble()
for (i in 1 until numbers.size) {
calculateNumber %= numbers[i].toDouble()
}
return if (calculateNumber % 1.0 == 0.0) {
calculateNumber.toInt().toString() // 정수로 반환
} else {
calculateNumber.toString() // 실수로 반환
}
}
계산식을 작성했으니 이제 =버튼을 눌렀을 때 각 연산으로 가도록 수정해줬다.
private fun calculateResult() {
val numbers = stringAnalyze.filterNumbers(currentInput)
val operators = stringAnalyze.filterOperators(currentInput)
if (numbers.isEmpty() || operators.isEmpty()){
displayText.text = "Error"
return
}
var result = ""
for (i in operators.indices) {
result = when(operators[i]){
"+" -> calculator.add(numbers)
"-" -> calculator.subtract(numbers)
"*" -> calculator.multiply(numbers)
"/" -> calculator.divide(numbers)
"%" -> calculator.mod(numbers)
else -> {
displayText.text = "Error"
return
}
}
}
displayText.text = result
currentInput = result
}
일단 numbers 변수에 StringAnalyze에서 currentInput을 넣어서 숫자만 뽑은 리스트를 넣어주고,
operator 에는 연산자만 뽑은 리스트를 넣는다. (여기까지 어제랑 똑같음)
그리고 만약 예외처리를 위해 numbers나 operators 가 비어있으면 Error 메세지를 띄우게함
그리고 결과를 넣을 변수 result를 만들어주고,
for 문으로 operators의 개수만큼 반복을 하면서 when 문으로 연산자에 맞추어서 calculator에 있는 함수를 실행하도록 만들어줬다.
그리고 마지막에 displayText의 텍스트와 currentInput에 result를 넣어줌
오늘만든거 결과

⏲️ 16 : 10 ~ 17 : 30

연산자를 하나밖에 구분못함
1+2-3 하면 0이 되어야하는데 마지막에 입력한 연산자 기준으로 모든 숫자를 처리해버림!
연산자를 연속으로 여러개 입력가능함
+-+- 이렇게도 입력이되어버림.. 연산자를 입력하고 만약에 다른 연산자를 입력하면 그 전에 입력한 연산자는 없어지게 해야할듯..하..
=을 누르면 입력한 식은 사라지고 답만 나오는데 입력했던 식이 위에 작게 표시되어도 괜찮을 것같다.
답으로 너무 너무 큰숫자나오면( Int 범위 벗어난 숫자) 어떻게 처리할지 결정하기
다음 단계 뭐 구현해나 미리 보려고 했는데 뭔말인지 모르겠어서
술쩍 사전캠프때 조원분들한테 SOS 날렸당
결국 스터디룸에서 모여서 만든 코드 봐주시고 서로 다음단계 어떻게 해야되는 걸지 얘기를 나눴당.
다른 분 코드를 보니까 이해안되던게 이해갔음 ~~! 속이 뻥!
나는 오늘 LV1 구현한다고 생각하고 했는데 하고나니 LV 2까지 구현해버린듯?
나머지 연산이 LV 2 에 해당하는 건지 모르고 같이 해버림
내일은 LV 3를 구현하면 되겠당 ~~!
⏲️ 공부시간 17 : 40 ~ 19 : 25
공부 계기
내배캠 1주차에 프로젝트를 진행하면서 내가 원하는 화면을 자유롭게 표현하려면
Android의 레이아웃을 빨리 공부해야겠다는 생각이 들어서 주말부터 Layout에 대한 공부를 시작함
나의 레이아웃 공부 방법
공부 내용
오늘은 어제에 이어서 Gridlayout 을 마저 공부했다.
어제 정리해둔 GridLayout의 속성들 중 고유 속성이 어떤것인지 따로 구분하고,
안드로이드 스튜디오로 직접 실습해보면서 속성들을 직접 사용해보면서
글로만 봤을 때 이해가 안되던 부분들을 직접 쓰면서 이해하려고 노력하고
내가 직접 설정해봐도 아리까리한 부분은 다시 구글링을 열심히해서 이해를 했다!
간단 정리
그리드 레이아웃에서 Orientation 을 적용하면, 적용한 방향의 줄? 은 개수를 지정하는게 의미가 없음
Ex) orientation 으로 horizontal을 적용했으면 정해진 column개수를 채울때까지 가로로 채워지다가
column을 채우면 그 다음 행으로 자동으로 넘어가서 row는 무한으로 늘어날 수 있다. 아무리 내가 제한해도 무시해버림
그리드레이아웃에서 alignmentMode를 통해서 마진을 포함한 크기로 정렬을할지, 딱 뷰의 경계선 만큼의 크기로 정렬을할지 결정해줄 수 있다.
rowOrderPreserved/columnOrderPreserved 이게 참 개념이 헷갈림
기본적인 설명에는 열/행의 순서를 보존할지 여부 이렇게 되어있는데 이렇게만 말해도 알아들으면 그 사람은 독심술사임 개발배울게아니라 한강가서 돗자리펴면 강남에 빌딩올릴듯
그래서 열심히 찾아보니깐 이걸 true로 해놓으면 그리드 레이아웃의 크기를 넘어가게 배치했을때 사이에 아무런 자식뷰도 배치 안해둔 빈 행이나 열이 있어도, 걔네를 다 표시하게 설정하는거고, false로 하면 레이아웃의 크기를 넘어서 뷰를 배치하면 그 사이에 빈 행이나 열이 있으면 걔네를 걍 덮어버리는거임!
일단 뭔지는 이제 알았는데 이걸 어떻게 활용해야할지는 감이 안온당
useDefaultMargis 를 true로 두면 안드로이드가 기본으로 각 자식들한테 8dp씩 마진을 준다.
근데 이 기본으로 주는 8dp는 변경할수가 없다고한다 그래서 많이 안쓴다고함!
Space View 라는 View가 있고 gridlayout을 사용하면서 중간에 빈 공간을 주고 싶을 때 얘를 넣으면 된다고함. 따로 기능은 없고 걍 자리만 차지하는 애인듯 학교다닐때 나같은 느낌으로다가
⏲️ 공부시간 19 : 25 ~ 20 : 35
시간이 약간 애매하게 남기도하고 해서 그냥 FrameLayout 복습을 하면서
벨로그랑 개발 인스타에 올릴 자료를 만들었다.
Framelayout에서 measureAllChildren 에 대해 이해했다고 생각했는데 자료 제작하려고 어떻게하면
한눈에 쉽게 이해할 수 있게 만들까 고민하면서 더 공부하다보니 그냥 글로 했을 때는 내가 이해 못했었구나 싶었다.
measureAllChildren은 FrameLayout의 기본원칙으로 FrameLayout의 크기를 wrap_content로 지정해놓으면 가장 큰 자식의 크기를 따라가는데, 자식뷰의 visibility가 “gone”으로 설정되었을 때에도 크기를 그대로 인정해줄지, 말지를 결정하는 거였음..
개념 수정하고나니까 원래 내가 어떻게 생각하던건지도 기억안나버림. 기억력 ㄹㅇ ㄹㅈㄷ임
오늘 점심먹기전에 다른조 분이 뭐 질문하러오셔서 뭐 보여드리느라 화면공유 켜놓고 끄는거 깜박해서
점심먹는동안 유투브 뭐보는지 다공개하면서 먹음
이렐킹이랑 운타라 영상 중계해버림