본문 바로가기
GDSC : KOTLIN STUDY

kotlin udemy 강의(122-123 정리 파트)

by 나영수 2022. 11. 10.

이 글은  유데미 강의 Android 12 및 Kotlin 개발 완전 정복를 참고하여 작성하였습니다.

작성자 : 나영수

개발환경은 Windows, Android Studio입니다.

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

1. dialog_brush_size.xml

 

imagebutton을 통해서 어떤 brushsize를 쓸건지 구현하는 파트이다.

small, medium, large를 각각 drawable파일에 구현해서 img를 불러오는 형식을 사용하였다.(즉 2번을 불러오게 되는 것이다.)

아래의 코드에서 가장 유용하게 사용하는 코드는 아마도 layout_constraintTop_toTopOf와 같은 속성이라고 생각한다.

위의 속성을 통해서 원하는 텍스트 혹은 이미지의 위치를 간단하게 구성시킬 수 있게 된다. 

 app:layout_constraintTop_toBottomOf="@id/ib_small_brush"이 코드는 ib_small_brush라는 id를 가진 tag의 아래에 존재한다는 위치를 명시하는 것이라고 생각하면 된다.

<?xml version="1.0" encoding="utf-8"?>

##imagebutton내부에서 app name을 사용하기 위해서는 app name space를 정의해 주어야 한다.

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">


##background가 아니더라도 src를 통해 필요한 파일의 경로를 적어서 구현할 수 있다.

    <ImageButton
        android:id="@+id/ib_small_brush"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="image"
        android:src="@drawable/small"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toTopOf="@+id/ib_medium_brush"/>

    <ImageButton
        android:id="@+id/ib_medium_brush"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="image"
        android:src="@drawable/medium"
        app:layout_constraintTop_toBottomOf="@id/ib_small_brush"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toTopOf="@+id/ib_large_brush"/>

    <ImageButton
        android:id="@+id/ib_large_brush"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="image"
        android:src="@drawable/large"
        app:layout_constraintTop_toBottomOf="@id/ib_medium_brush"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

 

 

2. drawable/small.xml

 

small, medium, large 모두 아래와 같은 양식을 이용해서 img를 생성하게 된다.

dither 속성을 사용함으로써 비트맵이 화면과 동일한 픽셀 구성을 가지지 않는경우에 사용하게 된다.

쉽게 말해서 hardware가 달라서 픽셀이 다르더라도 자동으로 이미지를 조정하게 하는 것이다. 이를 통해 이미지가 깨지거나 흐려보이는 일을 방지할 수 있다.

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:dither="true"
    android:shape="oval" >

    <size
        android:height="10dp"
        android:width="10dp" />

##배경색을 지정하게 된다.
    <solid android:color="#FF666666" />
</shape>

 

3. MainActivity.kt

 

showBrushSizeChooserDialog를 통해서 brush의 size를 정하는 팝업창을 띄우게 된다.

brushDialog를 Dialog 객체로 생성하여 1번에서 만들어 놓은 layout을 사용하도록 한다.

drawingSize를 처음에는 default 값으로 20으로 설정했지만 small, medium, large가 사용될때 마다 size가 변환되게 한다.

 

package eu.tutorials.kidsdrawingapp

import android.Manifest
import android.app.Dialog
import android.os.Bundle
import android.view.View
import android.widget.ImageButton
import android.widget.LinearLayout
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.view.get

class MainActivity : AppCompatActivity() {
    private var drawingView: DrawingView? = null
    private var mImageButtonCurrentPaint: ImageButton? =
        null // A variable for current color is picked from color pallet.

    ## 팝업을 만드는 함수(26번째 줄을 통해서 layout을 적용시키게 된다.)
    private fun showBrushSizeChooserDialog() {
        val brushDialog = Dialog(this)
        brushDialog.setContentView(R.layout.dialog_brush_size)
        brushDialog.setTitle("Brush size :")
        
        ##brushDialog내의 ib_small_brush라는 id를 찾아서 imageButton type의 smallBtn에 넣는다
        
        val smallBtn: ImageButton = brushDialog.findViewById(R.id.ib_small_brush)
        
        #click event가 발생했을때의 drawingView를 설정하고 dismiss를 통해서 더이상 brushDialog를
        #띄우지 않게 하는 것이다.
        #즉 brushSize를 정하게 되면 원래 화면에 띄어있던 팝업을 없애는 역할을 dismiss()가 하는 것이다.
        
        smallBtn.setOnClickListener(View.OnClickListener {
            drawingView?.setSizeForBrush(10.toFloat())
            brushDialog.dismiss()
        })
        val mediumBtn: ImageButton = brushDialog.findViewById(R.id.ib_medium_brush)
        mediumBtn.setOnClickListener(View.OnClickListener {
            drawingView?.setSizeForBrush(20.toFloat())
            brushDialog.dismiss()
        })

        val largeBtn: ImageButton = brushDialog.findViewById(R.id.ib_large_brush)
        largeBtn.setOnClickListener(View.OnClickListener {
            drawingView?.setSizeForBrush(30.toFloat())
            brushDialog.dismiss()
        })
        brushDialog.show()
    }

   
  
    fun paintClicked(view: View) {
        if (view !== mImageButtonCurrentPaint) {
            // Update the color
            val imageButton = view as ImageButton
            // Here the tag is used for swaping the current color with previous color.
            // The tag stores the selected view
            val colorTag = imageButton.tag.toString()
            // The color is set as per the selected tag here.
            drawingView?.setColor(colorTag)
            // Swap the backgrounds for last active and currently active image button.
            imageButton.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.pallet_pressed))
            mImageButtonCurrentPaint?.setImageDrawable(
                ContextCompat.getDrawable(
                    this,
                    R.drawable.pallet_normal
                )
            )

        }
    }

}

4. activity_main.xml

 

색상을 주기 위해서 간단한 imagebutton들을 activity_main.xml에서 구현하게 된다.

drawable/pallet_normal.xml을 통해서 default shape을 정의하게 된다. padding을 일부러 0dp로 모두 맞춰놓은 이유는 padding의 default값이 어떻게 될 지 모르기 때문에 위치의 변경을 막기위해서 선언했다고 한다.

corners에 radius를 10dp로 줌으로써 색깔을 나타내는 pallet가 동그라미 형식으로 보일 수 있도록 하였다.

또한 pallet_pressed.xml를 통해서 색깔을 선택했을 때 선택이 잘 되었다는 것을 가시적으로 잘 보이게 만들었다.

그리고 너무 긴 코드여서 가지고 오지는 않았지만 사실 activity_main.xml에서는 imagebutton의 색상과 같은 구현을 하드코딩을 통해서 모두 선언한다.

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <stroke
                android:width="2dp"
                android:color="#FF999999" />

            <solid android:color="#00000000" />

            <padding
                android:bottom="0dp"
                android:left="0dp"
                android:right="0dp"
                android:top="0dp" />
        </shape>
    </item>
    <item>
        <shape>
            <stroke
                android:width="2dp"
                android:color="#FF999999" />
            <solid android:color="#00000000" />
            <corners android:radius="10dp" />
        </shape>
    </item>
</layer-list>

5. id는 선언하지 않지만 index를 사용해서 원하는 imagebutton을 가져오는 방식

 

아래의 onCreate 함수 내에  1. 2. 로 표기한 부분을 보면 1.에서 먼저 ll_paint_colors를 id를 가진 LinearLayout을 불러온다.

그리고 2에서는 1번 index에 해당하는 linearlayout내부의 imageButton을 가져오게 된다. 이렇게 하면 imageButton에 일일이 id를 붙이는 번거로움을 피하고도 원하는 imageButton을 가져오는 효과를 얻을 수 있게 된다.

 

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        drawingView = findViewById(R.id.drawing_view)
        val ibBrush: ImageButton = findViewById(R.id.ib_brush)
        drawingView?.setSizeForBrush(20.toFloat())
        1. val linearLayoutPaintColors = findViewById<LinearLayout>(R.id.ll_paint_colors)
        2. mImageButtonCurrentPaint = linearLayoutPaintColors[1] as ImageButton
        mImageButtonCurrentPaint?.setImageDrawable(
            ContextCompat.getDrawable(
                this,
                R.drawable.pallet_pressed
            )
        )
        ibBrush.setOnClickListener {
            showBrushSizeChooserDialog()
        }
    }