diff --git a/app/build.gradle b/app/build.gradle index b4711913..938959fe 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,13 +4,13 @@ plugins { } android { - compileSdkVersion 30 - buildToolsVersion "30.0.3" + compileSdkVersion 34 + namespace = "otus.homework.customview" defaultConfig { applicationId "otus.homework.customview" minSdkVersion 23 - targetSdkVersion 30 + targetSdkVersion 34 versionCode 1 versionName "1.0" @@ -24,11 +24,11 @@ android { } } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } kotlinOptions { - jvmTarget = '1.8' + jvmTarget = '17' } } @@ -40,6 +40,7 @@ dependencies { implementation 'com.google.android.material:material:1.3.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' testImplementation 'junit:junit:4.+' + implementation 'com.google.code.gson:gson:2.10.1' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index efd1e519..0af130d3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -10,7 +10,8 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.CustomView"> - + diff --git a/app/src/main/java/otus/homework/customview/GraphBarView.kt b/app/src/main/java/otus/homework/customview/GraphBarView.kt new file mode 100644 index 00000000..09675af7 --- /dev/null +++ b/app/src/main/java/otus/homework/customview/GraphBarView.kt @@ -0,0 +1,164 @@ +package otus.homework.customview + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.Path +import android.util.AttributeSet +import android.view.View +import otus.homework.customview.data.GraphBarModel + +class GraphBarView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null +) : View(context, attrs) { + + private var maxPrice: Int = 2000 + private val stepsPrice: Int = 5 + private val stepsDate: Int = 16 + private val maxVerticalLine = 500f + private val paddingHorizontal = 50f + private var list: ArrayList = arrayListOf() + + private val paintText = Paint().apply { + color = Color.GRAY + } + + private val paintGrid = Paint().apply { + color = Color.LTGRAY + strokeWidth = 2f + style = Paint.Style.STROKE + } + + private val paintLine = Paint().apply { + strokeWidth = 8f + style = Paint.Style.STROKE + strokeCap = Paint.Cap.ROUND + strokeJoin = Paint.Join.ROUND + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + val wMode = MeasureSpec.getMode(widthMeasureSpec) + val hMode = MeasureSpec.getMode(heightMeasureSpec) + val wSize = MeasureSpec.getSize(widthMeasureSpec) + val hSize = MeasureSpec.getSize(heightMeasureSpec) + + when (wMode) { + MeasureSpec.EXACTLY -> { + setMeasuredDimension(wSize, hSize) + } + + MeasureSpec.AT_MOST -> { + setMeasuredDimension(wSize, hSize) + } + + MeasureSpec.UNSPECIFIED -> { + setMeasuredDimension(wSize, hSize) + } + } + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + + drawPrice(canvas) + } + + fun setMaxPrice(newMaxPrice: Int) { + maxPrice = newMaxPrice + } + + private fun drawPrice(canvas: Canvas) { + val stepPriceForGrid = maxPrice / stepsPrice.minus(1) + val stepDateForGrid = (measuredWidth - paddingHorizontal.times(2)) / stepsDate.minus(1) + + repeat(stepsPrice) { + val sum = maxPrice - stepPriceForGrid.times(it) + canvas.drawLine( + 0f + paddingHorizontal, + 100f + it * 100f, + measuredWidth.toFloat() - paddingHorizontal, + 100f + it * 100f, + paintGrid + ) + canvas.drawText( + "$sum ₽", + measuredWidth - 100f, + 50f + it * 100f + paddingHorizontal.div(2), + paintText.apply { textSize = 32f }) + } + + repeat(stepsDate) { + canvas.drawLine( + (it * stepDateForGrid) + paddingHorizontal, + 0f + paddingHorizontal.times(2), + (it * stepDateForGrid) + paddingHorizontal, + maxVerticalLine, + paintGrid + ) + canvas.drawText( + if (it == 0) "1" else "${((it + 1) * 2) - 1}", + (it * stepDateForGrid) + paddingHorizontal - paddingHorizontal.div(4), + maxVerticalLine.plus(100), + paintText.apply { textSize = 28f }) + } + + list.map { data -> + val listDays = data.listCategory.map { it.day } + paintLine.apply { + color = data.color + } + + val path = Path() + + if (data.listCategory.first().day == 1) { + val sumFirst = data.listCategory.first().sum + val percentFirst = sumFirst.toFloat().div(maxPrice.toFloat()) + path.moveTo( + 0f + paddingHorizontal, + (maxVerticalLine) - maxVerticalLine.minus(100f).times(percentFirst) + ) + + } else + path.moveTo(0f + paddingHorizontal, maxVerticalLine) + + repeat(stepsDate.times(2).minus(1)) { repeatInt -> + if (listDays.contains(repeatInt.plus(1))) { + val currSum = data.listCategory.find { it.day == repeatInt.plus(1) }?.sum + val percent = currSum?.toFloat()?.div(maxPrice.toFloat()) ?: 0f + path.quadTo( + (repeatInt * (stepDateForGrid / 2)) + paddingHorizontal, + (maxVerticalLine) - maxVerticalLine.minus(100f).times(percent), + (repeatInt * (stepDateForGrid / 2)) + paddingHorizontal, + (maxVerticalLine) - maxVerticalLine.minus(100f).times(percent) + ) + path.moveTo( + (repeatInt * (stepDateForGrid / 2)) + paddingHorizontal, + (maxVerticalLine) - maxVerticalLine.minus(100f).times(percent) + ) + } else { + path.quadTo( + (repeatInt * (stepDateForGrid / 2)) + paddingHorizontal, + maxVerticalLine, + (repeatInt * (stepDateForGrid / 2)) + paddingHorizontal, + maxVerticalLine + ) + path.moveTo( + (repeatInt * (stepDateForGrid / 2)) + paddingHorizontal, + maxVerticalLine + ) + } + } + + canvas.drawPath(path, paintLine) + } + } + + fun setList(newList: List) { + list.clear() + list.addAll(newList) + requestLayout() + invalidate() + } +} \ No newline at end of file diff --git a/app/src/main/java/otus/homework/customview/MainActivity.kt b/app/src/main/java/otus/homework/customview/MainActivity.kt index 78cb9448..237dff49 100644 --- a/app/src/main/java/otus/homework/customview/MainActivity.kt +++ b/app/src/main/java/otus/homework/customview/MainActivity.kt @@ -1,11 +1,213 @@ package otus.homework.customview -import androidx.appcompat.app.AppCompatActivity +import android.graphics.Color import android.os.Bundle +import android.util.Log +import android.view.View +import android.widget.Button +import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.isVisible +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import otus.homework.customview.data.CategoryForList +import otus.homework.customview.data.GraphBarModel +import otus.homework.customview.data.PayloadModel +import otus.homework.customview.data.PieChartModel +import otus.homework.customview.utils.toDateOnlyDayString -class MainActivity : AppCompatActivity() { +class MainActivity : AppCompatActivity(R.layout.activity_main) { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) + + val pieChartView = findViewById(R.id.pc) + val graphBarView = findViewById(R.id.gb) + val button = findViewById