[Android] Custom View ProgressBar 사용하기

Sdoubleu·2024년 6월 26일
0

Android

목록 보기
11/16
post-thumbnail

목표

home_progressbar_green.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 프로그래스바의 바탕 색깔 -->
    <item android:id="@android:id/background">
        <shape>
            <gradient
                android:angle="270"
                android:centerColor="@color/gray1"
                android:centerY="1.0"
                android:endColor="@color/gray1"
                android:startColor="@color/gray1" />
        </shape>
    </item>

    <!-- 프로그래스바의 진행률 색깔 선택 -->
    <item android:id="@android:id/progress">
        <clip>
            <shape>
                <gradient
                    android:angle="0"
                    android:centerX="0.25"
                    android:endColor="@color/gredient_start"
                    android:startColor="@color/gredient_end" />
            </shape>
        </clip>
    </item>
</layer-list>

centerColor를 통해 3가지 색으로 그라데이션을 넣을 수 있지만
저는 2가지 색의 그라데이션만 필요하기 때문에 center를 제외했습니다


layout_GredientProgressbar.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="wrap_content">

    <ProgressBar
        android:id="@+id/pb_home_progressbar"
        style="@style/HorizontalProgressBarStyle"
        android:layout_marginTop="50dp"
        android:progressDrawable="@drawable/home_progressbar_green"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:progress="100" />

    <TextView
        android:id="@+id/tv_home_total_kcal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="28dp"
        android:background="@drawable/home_kcal_background"
        android:gravity="center_horizontal"
        android:includeFontPadding="false"
        android:paddingStart="4dp"
        android:paddingEnd="4dp"
        android:paddingBottom="10dp"
        android:textAppearance="@style/Bold.Body6"
        android:textColor="@color/gray4"
        app:layout_constraintBottom_toTopOf="@+id/pb_home_progressbar"
        app:layout_constraintEnd_toEndOf="parent"
        tools:text="100kcal" />

    <TextView
        android:id="@+id/tv_home_now_kcal"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@drawable/home_kcal_background"
        android:gravity="end"
        android:includeFontPadding="false"
        android:paddingStart="4dp"
        android:paddingEnd="4dp"
        android:paddingBottom="10dp"
        android:textAppearance="@style/Bold.Body6"
        android:textColor="@color/base3"
        android:visibility="invisible"
        app:layout_constraintBottom_toTopOf="@+id/pb_home_progressbar"
        app:layout_constraintStart_toStartOf="parent"
        tools:text="100 kcal" />

</androidx.constraintlayout.widget.ConstraintLayout>

progressBar의 width와 height의 길이를 조정하는 부분을 style에서 코드를 작성해줍니다

tv_home_total_kcal의 위치는 고정 시키고 값만 변화시켜주고
tv_home_now_kcal의 위치는 서버에서 받아온 데이터를 비율에 맞게 이동시켜줄 것 입니다


⭐ CustomProgressBar.kt

class CustomProgressbar @JvmOverloads constructor(
    context: Context,
    attributeSet: AttributeSet? = null,
    defStyleAttr: Int = 0
) :
    LinearLayout(context, attributeSet, defStyleAttr) {

    val kcalMax = 100
    var currentkcal = 0
        private set

    var currentKcalLength = 0
        private set

    val binding: LayoutHomeGredientProgressbarBinding =
 LayoutHomeGredientProgressbarBinding.inflate(LayoutInflater.from(context), this, true)

    init {
        binding.pbHomeProgressbar.max = kcalMax
        setTextView(0, binding.tvHomeNowKcal)
        setTextView(kcalMax, binding.tvHomeTotalKcal)
    }

    fun setCurrentKcal(kcal: Int) {
        currentkcal = kcal
        binding.pbHomeProgressbar.progress = currentkcal
        var leftMargine = 0
        
        when(currentKcalLength) {
            in 0..1 -> {
                leftMargine = getSizeProgress() * currentkcal  / kcalMax - 105
            }
            2 -> {
                leftMargine = getSizeProgress() * currentkcal  / kcalMax - 120
            }
            3 -> {
                leftMargine = getSizeProgress() * currentkcal  / kcalMax - 140
            }
            4 -> {
                leftMargine = getSizeProgress() * currentkcal  / kcalMax - 160
            }
        }

        Log.d("length",currentKcalLength.toString())
        binding.tvHomeNowKcal.updateLayoutParams<MarginLayoutParams> {
            this.marginStart = leftMargine
        }
    }

    fun getSizeProgress(): Int {
        return binding.pbHomeProgressbar.width
    }

    fun setCurrentKcalLength(kcal: Int) {
        currentKcalLength = kcal.toString().length
    }

    fun setTextView(progress: Int, textview: TextView) {
        textview.setText("${progress} kcal")
    }
}
  • var kcalMax = 100
    비율로 위치를 움직이려 하기 때문에 100으로 고정했습니다

  • var currentKcal = 0
    현재 kcal의 값. 초깃값은 0 입니다

  • var currentKcalLength = 0
    받아온 현재 kcal의 string 길이. 초깃값은 0 입니다

  • private set
    멤버 변수의 setter를 private로 지정하여, 클래스 외부에서 해당 변수를 직접 접근하여 수정할 수 없게 함으로써, 보다 안전하게 관리할 수 있게 합니다

  • fun getSizeProgress()
    프로그레스바의 너비를 계산합니다
    프로그래스바의 실제 너비를 구하기 위해서 패딩을 설정했다면 아래와 같이 패딩을 빼주면 됩니다

binding.apply {
            pbHomeProgressbar.apply {
                width - paddingLeft - paddingRight
            }
        }
  • fun setCurrentKcal(kcal: Int)
    leftMargine 변수를 사용하여 텍스트 뷰의 좌측 마진을 계산하여 위치를 조정해줍니다

그림과 같이 달라진 값의 비율만큼 now의 위치를 이동시키는 함수이지만
TextView에 같은 자릿수더라도 숫자가 달라지면 약간의 사이즈가 달라지게 되는데
미숙하여 정확하게 맞추는 방법을 모르겠습니다 ...😅
혹시나 아시는 분 있으면 댓글 부탁드립니다 !


fragment.xml

<com.project.veganlife.home.CustomProgressbar
	android:id="@+id/cp_home_progressbar"
	android:layout_width="0dp"
	android:layout_height="wrap_content"
	app:layout_constraintBottom_toTopOf="@id/cl_home_kcal"
	app:layout_constraintEnd_toEndOf="parent"
	app:layout_constraintStart_toStartOf="parent" />

사용하려는 fragment에서 불러와주시면 됩니다 !


✏️

지난 포스팅과는 크게 달라졌다고 볼 수는 없지만 전과는 달리 부분 개선을 진행했습니다

profile
개발자희망자

0개의 댓글

관련 채용 정보