Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- spring exceptionHandler reposnse stackTrace
- IT 포지션 변경
- spring exception cause remove
- spring dynamic query sql injection
- ec2 scp 파일 전송
- 개발 포지션 변경
- spring sql injection 방지
- 운영체제 자원관리
- 운영체제 다중모드
- android 타이머
- aws ec2 scp 파일 전송
- spring exception stackTrace remove
- 운영체제 멀티 태스킹
- 운영체제 공룡책
- spring paging sort sql injection
- 백엔드 포지션 변경
- 개발 직무 변경
- spring exceptionHandler response cause
- spring sql injection
- spring 동적 쿼리 주의사항
- OS 자원관리
- 운영체제 작동방식
- 백엔드 직무 변경
- IT 직무 변경
- 운영체제 멀티 프로그래밍
- spring responseEntity response stackTrace
- 운영체제 커널모드
- Android Timer
- 운영체제 개념
- spring responseEntity response cause
Archives
- Today
- Total
오늘도 삽질중
Android MulitGradient Circle ProgressBar programmatically 본문
반응형
멀티 그라데이션 원형 프로그래스바를 프로그래밍으로 구현해보았습니다.
3개 이상의 색으로 그라데이션을 표현해 줘야 되는데, 구글링을 해보니 XML 방식으로 세팅하는건 최대 2가지 색 조합만 가능한 것으로 확인했습니다.
페인트과 애니메이션을 사용해서 구현을 했고, 그라데이션은 LinearGradient 를 사용했습니다.
프로그래밍으로 구현을 했으니 컬러 변경이 필요한 경우 컬러 코드값만 변경해주므로 변경에도 용이하다 판단됩니다.
또한 애니메이션을 적용해서 stop and restart 개념도 작업을 했습니다.
import android.animation.Animator
import android.animation.ObjectAnimator
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.util.TypedValue
import android.view.View
import android.view.animation.LinearInterpolator
import androidx.annotation.Keep
/**
* Created by genesislab_Jeong-Hyun. 2022/04/06
*/
class MultiGradientCircleProgressBar constructor(
context: Context,
attr: AttributeSet
) : View(context,attr) {
private val stroke = context.dpToPx(6).toFloat()
private val backgroundPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
color = Color.parseColor("#80000000")
}
private val gradientBoardPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
color = Color.parseColor("#7b7b7b")
style = Paint.Style.STROKE
strokeWidth = stroke
isAntiAlias = true
}
private val progressBoardPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
color = Color.parseColor("#7b7b7b")
style = Paint.Style.STROKE
strokeWidth = stroke
isAntiAlias = true
}
private var boardRectF = RectF()
private var animator: ObjectAnimator? = null
@Keep
private var sweep: Float = 0f
set(value) {
field = value
invalidate()
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
boardRectF.set(
stroke/2f,
stroke/2f,
width.toFloat() - stroke/2f,
height.toFloat() - stroke/2f
)
LinearGradient(
0f, 0f, width.toFloat(), 0f,
intArrayOf(
Color.parseColor("#7859de"),
Color.parseColor("#e62983"),
Color.parseColor("#ee7625")
),
floatArrayOf(0f,0.23f, 0.81f),
Shader.TileMode.CLAMP
).also {
gradientBoardPaint.shader = it
// 멀티 그라데이션 프로그래스바가 보여지고 싶다면 아래 코드로 변경
// progressBoardPaint.shader = it
}
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
canvas?.drawCircle(width/2f , height/2f , width/2f , backgroundPaint)
canvas?.drawArc(boardRectF, 0f,360f,false , gradientBoardPaint)
canvas?.drawArc(boardRectF , 270f,sweep , false , progressBoardPaint)
}
fun setProgress(p: Int) {
sweep = p.toFloat() / 100f * 360f
}
fun reset(){
sweep = 0f
}
@Keep
fun startAnimation(duration: Float){
ObjectAnimator.ofFloat(this , "sweep", 0f, 360f+OFF_SET).apply {
this.duration = (duration * 1000).toLong()
interpolator = LinearInterpolator()
addListener(object : Animator.AnimatorListener{
override fun onAnimationStart(animation: Animator?) {}
override fun onAnimationEnd(animation: Animator?) { animator = null }
override fun onAnimationCancel(animation: Animator?) { animator = null }
override fun onAnimationRepeat(animation: Animator?) {}
})
}.also {
animator = it
}.start()
}
fun isRunning() = animator?.isRunning?: false
fun isPaused() = animator?.isPaused?: false
fun pauseAnimation(){
if (animator?.isRunning == true) animator?.pause()
}
fun resumeAnimation(){
if (animator?.isPaused == true) animator?.resume()
}
private fun Context.dpToPx(dp: Int): Int {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP , dp.toFloat() , this.resources.displayMetrics).toInt()
}
companion object {
const val OFF_SET = 8
}
}
해당코드를 적용후 XML 에서 기본 Ui 쓰는것처럼 사용하시면 됩니다.
<?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"
tools:context=".MainActivity">
<ai.genesislab.mulitgradientcircleprogressbar.MultiGradientCircleProgressBar
android:id="@+id/progressbar"
android:layout_width="84dp"
android:layout_height="84dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
액티비티에서 해당 뷰에 접근하여 아래처럼 실행합니다. (샘플 프로젝트라 findViewById 로 접근했으나, 원래는 데이터바인딩 또는 뷰 바인딩을 사용합니다.)
class MainActivity : AppCompatActivity() {
private val progressBar: MultiGradientCircleProgressBar by lazy {
findViewById(R.id.progressbar)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//1f -> 1초
progressBar.startAnimation(10f)
//stop animation
// progressBar.pauseAnimation()
//resume animation
// progressBar.resumeAnimation()
}
}
결과 영상입니다.
위 영상과 반대로 그라데이션 색깔이 서서히 나타나게 하고 싶다면 onSizeChanged 를 아래처럼 변경 후 실행하면 됩니다.
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
boardRectF.set(
stroke/2f,
stroke/2f,
width.toFloat() - stroke/2f,
height.toFloat() - stroke/2f
)
LinearGradient(
0f, 0f, width.toFloat(), 0f,
intArrayOf(
Color.parseColor("#7859de"),
Color.parseColor("#e62983"),
Color.parseColor("#ee7625")
),
floatArrayOf(0f,0.23f, 0.81f),
Shader.TileMode.CLAMP
).also {
// gradientBoardPaint.shader = it
// 멀티 그라데이션 프로그래스바가 보여지고 싶다면 아래 코드로 변경
progressBoardPaint.shader = it
}
}
결과 영상입니다.
반응형
'안드로이드' 카테고리의 다른 글
Android Play Asset Delivery 구현하기 (2) | 2022.02.02 |
---|---|
Android Compose Scroll Bottom Button (0) | 2022.01.04 |
Android Compose TextField 를 쓰다가 네이티브로 변경한 이유 (0) | 2021.12.29 |
Android Gradient rounded corner programmatically (0) | 2021.12.22 |
Android View 의 절대좌표가 맞지 않을경우 (0) | 2021.12.21 |
Comments