From e0160591b76d21966c4bec83dd88285c003dbaa9 Mon Sep 17 00:00:00 2001 From: Alexander Date: Wed, 7 Jun 2023 11:42:21 +0200 Subject: [PATCH 1/3] pieChart --- app/build.gradle | 26 +++-- app/src/main/AndroidManifest.xml | 4 +- .../otus/homework/customview/ChartModel.kt | 25 +++++ .../java/otus/homework/customview/ListData.kt | 10 ++ .../otus/homework/customview/MainActivity.kt | 13 ++- .../java/otus/homework/customview/MyApp.kt | 14 +++ .../otus/homework/customview/MyChartView.kt | 103 ++++++++++++++++++ .../java/otus/homework/customview/PayLoad.kt | 13 +++ app/src/main/res/layout/activity_main.xml | 11 +- build.gradle | 8 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 11 files changed, 207 insertions(+), 22 deletions(-) create mode 100644 app/src/main/java/otus/homework/customview/ChartModel.kt create mode 100644 app/src/main/java/otus/homework/customview/ListData.kt create mode 100644 app/src/main/java/otus/homework/customview/MyApp.kt create mode 100644 app/src/main/java/otus/homework/customview/MyChartView.kt create mode 100644 app/src/main/java/otus/homework/customview/PayLoad.kt diff --git a/app/build.gradle b/app/build.gradle index b4711913..30c057ca 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,16 +1,21 @@ plugins { id 'com.android.application' id 'kotlin-android' + id 'kotlin-parcelize' } android { - compileSdkVersion 30 - buildToolsVersion "30.0.3" + compileSdkVersion 33 + buildToolsVersion "33.0.2" + + buildFeatures { + viewBinding = true + } defaultConfig { applicationId "otus.homework.customview" - minSdkVersion 23 - targetSdkVersion 30 + minSdkVersion 24 + targetSdkVersion 33 versionCode 1 versionName "1.0" @@ -24,8 +29,8 @@ android { } } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 } kotlinOptions { jvmTarget = '1.8' @@ -35,10 +40,11 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation 'androidx.core:core-ktx:1.3.2' - implementation 'androidx.appcompat:appcompat:1.2.0' - implementation 'com.google.android.material:material:1.3.0' - implementation 'androidx.constraintlayout:constraintlayout:2.0.4' + implementation 'androidx.core:core-ktx:1.10.1' + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'com.google.android.material:material:1.9.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'com.google.code.gson:gson:2.8.9' testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index efd1e519..277f0d10 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -4,13 +4,15 @@ package="otus.homework.customview"> - + diff --git a/app/src/main/java/otus/homework/customview/ChartModel.kt b/app/src/main/java/otus/homework/customview/ChartModel.kt new file mode 100644 index 00000000..5cb6a1ac --- /dev/null +++ b/app/src/main/java/otus/homework/customview/ChartModel.kt @@ -0,0 +1,25 @@ +package otus.homework.customview + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import otus.homework.customview.MyApp.Companion.myResource +import java.nio.charset.Charset + +class ChartModel() : ViewModel() { + + val myData = getData() + val pieData:Map = grafData() + + fun grafData() = myData.groupingBy {it.category} + .fold(0) { summ, category -> summ + category.amount } + + fun getData(): List{ + val gson = Gson() + val type = object : TypeToken>() {}.type + myResource.reset() + val myJson = myResource.bufferedReader(Charset.defaultCharset()) + return gson.fromJson>(myJson, type) + } +} diff --git a/app/src/main/java/otus/homework/customview/ListData.kt b/app/src/main/java/otus/homework/customview/ListData.kt new file mode 100644 index 00000000..fc7ea8aa --- /dev/null +++ b/app/src/main/java/otus/homework/customview/ListData.kt @@ -0,0 +1,10 @@ +package otus.homework.customview + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + + +@Parcelize +data class ListData ( + var data:Map +): Parcelable diff --git a/app/src/main/java/otus/homework/customview/MainActivity.kt b/app/src/main/java/otus/homework/customview/MainActivity.kt index 78cb9448..13344193 100644 --- a/app/src/main/java/otus/homework/customview/MainActivity.kt +++ b/app/src/main/java/otus/homework/customview/MainActivity.kt @@ -1,11 +1,20 @@ package otus.homework.customview -import androidx.appcompat.app.AppCompatActivity import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import otus.homework.customview.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { + val chartModel : ChartModel + + init{ + chartModel = ChartModel() + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) + val binding = ActivityMainBinding.inflate(layoutInflater) + val view = binding.root + setContentView(view) } } \ No newline at end of file diff --git a/app/src/main/java/otus/homework/customview/MyApp.kt b/app/src/main/java/otus/homework/customview/MyApp.kt new file mode 100644 index 00000000..3d944610 --- /dev/null +++ b/app/src/main/java/otus/homework/customview/MyApp.kt @@ -0,0 +1,14 @@ +package otus.homework.customview + +import android.app.Application +import java.io.InputStream + +class MyApp: Application() { + companion object{ + lateinit var myResource: InputStream} + override fun onCreate(){ + super.onCreate() + myResource = this.resources.openRawResource(R.raw.payload) + } + +} \ No newline at end of file diff --git a/app/src/main/java/otus/homework/customview/MyChartView.kt b/app/src/main/java/otus/homework/customview/MyChartView.kt new file mode 100644 index 00000000..4a65c139 --- /dev/null +++ b/app/src/main/java/otus/homework/customview/MyChartView.kt @@ -0,0 +1,103 @@ +package otus.homework.customview + +import android.content.Context +import android.graphics.* +import android.os.Bundle +import android.os.Parcelable +import android.util.AttributeSet +import android.view.View + + +class MyChartView : View { + constructor(context: Context?) : super(context) + constructor(context: Context?, attributeSet: AttributeSet?) : super(context, attributeSet) + + private val rec = RectF() + private val color = arrayOf( + Color.RED, + Color.BLUE, + -0x886699, + -0x11BB88, + Color.CYAN, + Color.GRAY, + Color.YELLOW, + Color.MAGENTA, + Color.GREEN + ) + private val pieData = ChartModel().pieData + private val sumData = pieData.map { it -> it.value }.sum() + + init { + rec.left = 0f + rec.top = 0f + isSaveEnabled = true + } + + override fun onSaveInstanceState(): Parcelable { + val bundle = Bundle() + bundle.putParcelable("superState", super.onSaveInstanceState()) + return bundle + } + + override fun onRestoreInstanceState(state: Parcelable?) { + var viewState = state + if (viewState is Bundle) { + viewState = viewState.getParcelable("superState") + } + super.onRestoreInstanceState(viewState) + } + + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + val finalWidth = getMeasuredWidth() * 3 / 4 + val finalHeight = getMeasuredWidth() * 3 / 4 + val widthMode = MeasureSpec.getMode(widthMeasureSpec) + val heightMode = MeasureSpec.getMode(heightMeasureSpec) + System.out.println("widthMode $widthMode heightMode $heightMode") + System.out.println("widthMode ${MeasureSpec.EXACTLY} heightMode ${MeasureSpec.AT_MOST}") + setMeasuredDimension(finalWidth, finalHeight) + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + val midHeight = height / 2f + val midWidth = width / 2f + val startLeft = width * 0.1f + val startTop = height * 0.1f + var startAngle = 0f + var sweepAngle = 0f + canvas.drawARGB(230, 400, 150, 50) + + val p = Paint() + p.isAntiAlias = true + p.color = Color.RED + p.style = Paint.Style.STROKE + p.strokeWidth = 40f + p.color = Color.BLACK + + val pText = Paint() + pText.textSize = 20f + pText.style = Paint.Style.FILL_AND_STROKE + pText.setStrokeWidth(2f) + + canvas.translate(0f, height / 4f) + var j = 0 + pieData.forEach { s, i -> + sweepAngle = (i * 360f) / sumData + p.color = color[j++ % 9] + canvas.drawArc(startLeft, startTop, midWidth, midHeight, startAngle, sweepAngle, false, p) + canvas.translate(midWidth * 1.2f, j * 50f) + textDraw(canvas, pText, p, s) + canvas.translate(-midWidth * 1.2f, -j * 50f) + startAngle += sweepAngle + } + } + + private fun textDraw(canvas: Canvas, p: Paint, pBack: Paint, text: String) { + val rect = Rect(20, 20, 170, 23) + canvas.drawRect(rect, pBack) + System.out.println("getTextLocale() $p.getTextLocale()") + canvas.drawText(text, 10f, 25f, p) + } +} \ No newline at end of file diff --git a/app/src/main/java/otus/homework/customview/PayLoad.kt b/app/src/main/java/otus/homework/customview/PayLoad.kt new file mode 100644 index 00000000..75d6b68c --- /dev/null +++ b/app/src/main/java/otus/homework/customview/PayLoad.kt @@ -0,0 +1,13 @@ +package otus.homework.customview + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class PayLoad( + val id: Long, + val name: String, + val amount: Int, + val category: String, + val time: Long +): Parcelable diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 79ae6993..85b9c6fb 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -5,15 +5,18 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" + android:layout_gravity="center" tools:context=".MainActivity"> - \ No newline at end of file diff --git a/build.gradle b/build.gradle index e47bb55b..fdd4bb43 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,12 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = "1.4.32" + ext.kotlin_version = "1.8.0" repositories { google() - jcenter() + mavenCentral() } dependencies { - classpath "com.android.tools.build:gradle:4.1.2" + classpath 'com.android.tools.build:gradle:7.2.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong @@ -17,7 +17,7 @@ buildscript { allprojects { repositories { google() - jcenter() + mavenCentral() } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8734448b..e49965f7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip From 0388159295f24d2bdc73afb549c07b6e47322c35 Mon Sep 17 00:00:00 2001 From: Alexander Date: Sat, 1 Jul 2023 14:56:53 +0200 Subject: [PATCH 2/3] new checked pieChart --- app/build.gradle | 7 +- app/src/main/AndroidManifest.xml | 1 - .../otus/homework/customview/ChartModel.kt | 47 ++++++- .../java/otus/homework/customview/ListData.kt | 6 +- .../otus/homework/customview/MainActivity.kt | 15 ++- .../java/otus/homework/customview/MyApp.kt | 14 +- .../otus/homework/customview/MyChartView.kt | 127 ++++++++++++------ .../otus/homework/customview/TouchView.kt | 10 ++ app/src/main/res/layout/activity_main.xml | 1 - 9 files changed, 164 insertions(+), 64 deletions(-) create mode 100644 app/src/main/java/otus/homework/customview/TouchView.kt diff --git a/app/build.gradle b/app/build.gradle index 30c057ca..a9927aab 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -45,7 +45,8 @@ dependencies { implementation 'com.google.android.material:material:1.9.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'com.google.code.gson:gson:2.8.9' - testImplementation 'junit:junit:4.+' - androidTestImplementation 'androidx.test.ext:junit:1.1.2' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + implementation 'androidx.activity:activity-ktx:1.7.2' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 277f0d10..3f3ddd9f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,7 +15,6 @@ android:exported="true"> - diff --git a/app/src/main/java/otus/homework/customview/ChartModel.kt b/app/src/main/java/otus/homework/customview/ChartModel.kt index 5cb6a1ac..5f9ca7f6 100644 --- a/app/src/main/java/otus/homework/customview/ChartModel.kt +++ b/app/src/main/java/otus/homework/customview/ChartModel.kt @@ -1,25 +1,58 @@ package otus.homework.customview import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider import com.google.gson.Gson import com.google.gson.reflect.TypeToken import otus.homework.customview.MyApp.Companion.myResource import java.nio.charset.Charset -class ChartModel() : ViewModel() { +class ChartModel : ViewModel() { - val myData = getData() - val pieData:Map = grafData() + var pieData: Map = HashMap() + var beginArc = ArrayList() + var lengthArc = ArrayList() + var scaleArc: List + var checkedIndex: Int = -1 + private val sumData: Int + private val myData: List + private var startAngle = 0f + private var sweepAngle = 0f - fun grafData() = myData.groupingBy {it.category} + init { + myData = loadData() + pieData = grafData() + sumData = pieData.map { it -> it.value }.sum() + pieData.forEach { _, i -> + beginArc.add(startAngle) + sweepAngle = (i * 360f) / sumData + lengthArc.add(sweepAngle) + System.out.println("startAngle $startAngle") + startAngle += sweepAngle + } + scaleArc = pieData.map { _ -> 1.0f } + } + + fun grafData() = myData.groupingBy { it.category } .fold(0) { summ, category -> summ + category.amount } - fun getData(): List{ + fun loadData(): List { val gson = Gson() val type = object : TypeToken>() {}.type myResource.reset() val myJson = myResource.bufferedReader(Charset.defaultCharset()) - return gson.fromJson>(myJson, type) + return gson.fromJson(myJson, type) + } + + fun setScale(sector: Int) { + scaleArc = scaleArc.mapIndexed { index, scale -> + if (index == sector) + 1.05f + else + 1.0f + } + } + + fun setChecked(index: Int) { + checkedIndex = index } } diff --git a/app/src/main/java/otus/homework/customview/ListData.kt b/app/src/main/java/otus/homework/customview/ListData.kt index fc7ea8aa..273aa8d7 100644 --- a/app/src/main/java/otus/homework/customview/ListData.kt +++ b/app/src/main/java/otus/homework/customview/ListData.kt @@ -5,6 +5,6 @@ import kotlinx.parcelize.Parcelize @Parcelize -data class ListData ( - var data:Map -): Parcelable +data class ListData( + var data: Map +) : Parcelable diff --git a/app/src/main/java/otus/homework/customview/MainActivity.kt b/app/src/main/java/otus/homework/customview/MainActivity.kt index 13344193..e7a977d3 100644 --- a/app/src/main/java/otus/homework/customview/MainActivity.kt +++ b/app/src/main/java/otus/homework/customview/MainActivity.kt @@ -1,20 +1,25 @@ package otus.homework.customview import android.os.Bundle +import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.Observer import otus.homework.customview.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { - val chartModel : ChartModel - - init{ - chartModel = ChartModel() - } + val chartModel: ChartModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val binding = ActivityMainBinding.inflate(layoutInflater) val view = binding.root + binding.chartView.chartModel = chartModel + val touchDown = binding.chartView._clickSector + touchDown.observe(this, { + chartModel.setChecked(it) + chartModel.setScale(it) + binding.chartView.invalidate() + }) setContentView(view) } } \ No newline at end of file diff --git a/app/src/main/java/otus/homework/customview/MyApp.kt b/app/src/main/java/otus/homework/customview/MyApp.kt index 3d944610..926860c9 100644 --- a/app/src/main/java/otus/homework/customview/MyApp.kt +++ b/app/src/main/java/otus/homework/customview/MyApp.kt @@ -3,12 +3,14 @@ package otus.homework.customview import android.app.Application import java.io.InputStream -class MyApp: Application() { - companion object{ - lateinit var myResource: InputStream} - override fun onCreate(){ - super.onCreate() - myResource = this.resources.openRawResource(R.raw.payload) +class MyApp : Application() { + companion object { + lateinit var myResource: InputStream + } + + override fun onCreate() { + super.onCreate() + myResource = this.resources.openRawResource(R.raw.payload) } } \ No newline at end of file diff --git a/app/src/main/java/otus/homework/customview/MyChartView.kt b/app/src/main/java/otus/homework/customview/MyChartView.kt index 4a65c139..e7dadd68 100644 --- a/app/src/main/java/otus/homework/customview/MyChartView.kt +++ b/app/src/main/java/otus/homework/customview/MyChartView.kt @@ -5,13 +5,23 @@ import android.graphics.* import android.os.Bundle import android.os.Parcelable import android.util.AttributeSet +import android.view.GestureDetector +import android.view.MotionEvent import android.view.View - +import androidx.lifecycle.MutableLiveData +import kotlin.math.pow class MyChartView : View { constructor(context: Context?) : super(context) constructor(context: Context?, attributeSet: AttributeSet?) : super(context, attributeSet) + var chartModel = ChartModel() + lateinit var cycleCenter: PointF + var _clickSector = MutableLiveData(-1) + + private val gestureDetector = GestureDetector(context, TouchView()) + private val pChart = Paint() + private val pText = Paint() private val rec = RectF() private val color = arrayOf( Color.RED, @@ -24,13 +34,22 @@ class MyChartView : View { Color.MAGENTA, Color.GREEN ) - private val pieData = ChartModel().pieData - private val sumData = pieData.map { it -> it.value }.sum() + private var startLeft = 0f + private var startTop = 0f + private var midHeight = 0f + private var midWidth = 0f init { rec.left = 0f rec.top = 0f isSaveEnabled = true + pChart.isAntiAlias = true + pChart.style = Paint.Style.STROKE + pChart.strokeWidth = 40f + pText.textSize = 20f + pText.style = Paint.Style.FILL_AND_STROKE + pText.setStrokeWidth(2f) + } override fun onSaveInstanceState(): Parcelable { @@ -47,57 +66,89 @@ class MyChartView : View { super.onRestoreInstanceState(viewState) } - override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) val finalWidth = getMeasuredWidth() * 3 / 4 val finalHeight = getMeasuredWidth() * 3 / 4 - val widthMode = MeasureSpec.getMode(widthMeasureSpec) - val heightMode = MeasureSpec.getMode(heightMeasureSpec) - System.out.println("widthMode $widthMode heightMode $heightMode") - System.out.println("widthMode ${MeasureSpec.EXACTLY} heightMode ${MeasureSpec.AT_MOST}") + System.out.println("finalWidth $finalWidth finalHeight $finalHeight") setMeasuredDimension(finalWidth, finalHeight) } override fun onDraw(canvas: Canvas) { super.onDraw(canvas) - val midHeight = height / 2f - val midWidth = width / 2f - val startLeft = width * 0.1f - val startTop = height * 0.1f - var startAngle = 0f - var sweepAngle = 0f - canvas.drawARGB(230, 400, 150, 50) + midHeight = Math.min(height, width) / 2f + midWidth = midHeight + startLeft = width * 0.1f + startTop = height * 0.1f + // Шаблон + canvas.drawARGB(230, 400, 150, 50) +// Сдвиг для правильного отображения в landscape + canvas.translate(0f, height / 4f) +// Рисование pieChart + cycleCenter = + PointF((midWidth + startLeft) / 2, (midHeight + startLeft) / 2 + height / 4f) + var j = 0 - val p = Paint() - p.isAntiAlias = true - p.color = Color.RED - p.style = Paint.Style.STROKE - p.strokeWidth = 40f - p.color = Color.BLACK + chartModel.pieData.forEach { s, _ -> + pChart.color = color[j % color.size] + canvas.drawArc( + startLeft - midWidth * (chartModel.scaleArc[j] - 1f), + startTop - midHeight * (chartModel.scaleArc[j] - 1f), + midWidth * chartModel.scaleArc[j], + midHeight * chartModel.scaleArc[j], + chartModel.beginArc.get(j), chartModel.lengthArc.get(j), + false, + pChart + ) +// В таблицу наименований + canvas.translate(midWidth * 1.2f, j * 50f) + if(j == chartModel.checkedIndex ){ + textDraw(canvas, pText, pChart, s+" !!") + } + else{ + textDraw(canvas, pText, pChart, s)} - val pText = Paint() - pText.textSize = 20f - pText.style = Paint.Style.FILL_AND_STROKE - pText.setStrokeWidth(2f) - - canvas.translate(0f, height / 4f) - var j = 0 - pieData.forEach { s, i -> - sweepAngle = (i * 360f) / sumData - p.color = color[j++ % 9] - canvas.drawArc(startLeft, startTop, midWidth, midHeight, startAngle, sweepAngle, false, p) - canvas.translate(midWidth * 1.2f, j * 50f) - textDraw(canvas, pText, p, s) - canvas.translate(-midWidth * 1.2f, -j * 50f) - startAngle += sweepAngle - } + canvas.translate(-midWidth * 1.2f, -j * 50f) + j++ + } } private fun textDraw(canvas: Canvas, p: Paint, pBack: Paint, text: String) { val rect = Rect(20, 20, 170, 23) canvas.drawRect(rect, pBack) - System.out.println("getTextLocale() $p.getTextLocale()") canvas.drawText(text, 10f, 25f, p) } + + override fun onTouchEvent(event: MotionEvent): Boolean { + gestureDetector.onTouchEvent(event) + val angle: Double + val lenghtX = event.x - cycleCenter.x + val lenghtY = event.y - cycleCenter.y + val touchVector = Math.sqrt( + (lenghtX.pow(2) + lenghtY.pow(2)).toDouble() + ) + if (touchVector < midHeight / 2) { + angle = (Math.atan((lenghtY / lenghtX).toDouble()) / Math.PI * 180).let { + if (lenghtX < 0f) { + it.plus(180.0) + } else { + if (lenghtY < 0f) { + it.plus(360.0) + } else { + it + } + } + } + run breaking@{ + chartModel.beginArc.forEachIndexed { index, beginAngle -> + if (beginAngle > angle) { + _clickSector.value = index - 1 + return@breaking + } + } + _clickSector.value = chartModel.beginArc.size - 1 + } + } + return super.onTouchEvent(event) + } } \ No newline at end of file diff --git a/app/src/main/java/otus/homework/customview/TouchView.kt b/app/src/main/java/otus/homework/customview/TouchView.kt new file mode 100644 index 00000000..fa13c269 --- /dev/null +++ b/app/src/main/java/otus/homework/customview/TouchView.kt @@ -0,0 +1,10 @@ +package otus.homework.customview + +import android.view.GestureDetector +import android.view.MotionEvent + +class TouchView: GestureDetector.SimpleOnGestureListener() { + override fun onDown(e: MotionEvent): Boolean { + return super.onDown(e) + } +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 85b9c6fb..12e396c0 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -8,7 +8,6 @@ android:layout_gravity="center" tools:context=".MainActivity"> - Date: Wed, 29 Nov 2023 18:44:46 +0100 Subject: [PATCH 3/3] TabLayout pieChart lineChart --- app/build.gradle | 30 +-- app/src/main/AndroidManifest.xml | 5 +- .../otus/homework/customview/MainActivity.kt | 47 +++-- .../otus/homework/customview/Tab1Fragment.kt | 33 ++++ .../otus/homework/customview/Tab2Fragment.kt | 26 +++ .../homework/customview/TabPagerAdapter.kt | 22 +++ .../customview/linechart/LineChartModel.kt | 24 +++ .../customview/linechart/LineChartView.kt | 185 ++++++++++++++++++ .../customview/{ => linechart}/TouchView.kt | 2 +- .../customview/{ => piechart}/ChartModel.kt | 19 +- .../PieChartView.kt} | 61 +++--- .../homework/customview/piechart/TouchView.kt | 10 + app/src/main/res/layout/activity_main.xml | 37 +++- app/src/main/res/layout/content_main.xml | 19 ++ app/src/main/res/layout/fragment_tab1.xml | 19 ++ app/src/main/res/layout/fragment_tab2.xml | 19 ++ app/src/main/res/values/strings.xml | 3 + build.gradle | 20 +- gradle.properties | 3 +- gradle/wrapper/gradle-wrapper.properties | 6 +- settings.gradle | 14 ++ 21 files changed, 513 insertions(+), 91 deletions(-) create mode 100644 app/src/main/java/otus/homework/customview/Tab1Fragment.kt create mode 100644 app/src/main/java/otus/homework/customview/Tab2Fragment.kt create mode 100644 app/src/main/java/otus/homework/customview/TabPagerAdapter.kt create mode 100644 app/src/main/java/otus/homework/customview/linechart/LineChartModel.kt create mode 100644 app/src/main/java/otus/homework/customview/linechart/LineChartView.kt rename app/src/main/java/otus/homework/customview/{ => linechart}/TouchView.kt (83%) rename app/src/main/java/otus/homework/customview/{ => piechart}/ChartModel.kt (74%) rename app/src/main/java/otus/homework/customview/{MyChartView.kt => piechart/PieChartView.kt} (74%) create mode 100644 app/src/main/java/otus/homework/customview/piechart/TouchView.kt create mode 100644 app/src/main/res/layout/content_main.xml create mode 100644 app/src/main/res/layout/fragment_tab1.xml create mode 100644 app/src/main/res/layout/fragment_tab2.xml diff --git a/app/build.gradle b/app/build.gradle index a9927aab..4cf60147 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,17 +5,13 @@ plugins { } android { - compileSdkVersion 33 + compileSdk 33 buildToolsVersion "33.0.2" - buildFeatures { - viewBinding = true - } - defaultConfig { - applicationId "otus.homework.customview" - minSdkVersion 24 - targetSdkVersion 33 + applicationId "ru.zatsoft" + minSdk 24 + targetSdk 33 versionCode 1 versionName "1.0" @@ -33,19 +29,31 @@ android { targetCompatibility JavaVersion.VERSION_11 } kotlinOptions { - jvmTarget = '1.8' + jvmTarget = '11' + } + buildFeatures { + viewBinding true } } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + constraints { + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.20") { + because("kotlin-stdlib-jdk7 is now a part of kotlin-stdlib") + } + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.20") { + because("kotlin-stdlib-jdk8 is now a part of kotlin-stdlib") + } + } implementation 'androidx.core:core-ktx:1.10.1' implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'com.google.android.material:material:1.9.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation 'com.google.code.gson:gson:2.8.9' + implementation 'com.google.code.gson:gson:2.10.1' implementation 'androidx.activity:activity-ktx:1.7.2' + implementation 'androidx.navigation:navigation-fragment:2.6.0' + testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3f3ddd9f..8355889a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,16 +1,17 @@ + android:theme="@style/Theme.CustomView" + tools:targetApi="31"> diff --git a/app/src/main/java/otus/homework/customview/MainActivity.kt b/app/src/main/java/otus/homework/customview/MainActivity.kt index e7a977d3..fd63e988 100644 --- a/app/src/main/java/otus/homework/customview/MainActivity.kt +++ b/app/src/main/java/otus/homework/customview/MainActivity.kt @@ -1,25 +1,44 @@ package otus.homework.customview import android.os.Bundle -import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity -import androidx.lifecycle.Observer +import com.google.android.material.tabs.TabLayoutMediator +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken import otus.homework.customview.databinding.ActivityMainBinding +import java.nio.charset.Charset class MainActivity : AppCompatActivity() { - val chartModel: ChartModel by viewModels() - + private lateinit var binding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val binding = ActivityMainBinding.inflate(layoutInflater) - val view = binding.root - binding.chartView.chartModel = chartModel - val touchDown = binding.chartView._clickSector - touchDown.observe(this, { - chartModel.setChecked(it) - chartModel.setScale(it) - binding.chartView.invalidate() - }) - setContentView(view) + binding = ActivityMainBinding.inflate(layoutInflater) + setContentView(binding.root) + configureTabLayout() + val adapter = TabPagerAdapter(this, binding.tabLayout.tabCount) + binding.viewPager.adapter = adapter + TabLayoutMediator(binding.tabLayout, binding.viewPager) + { tab, position -> + tab.text = MYTITLE.get(position) + }.attach() + } + + private fun configureTabLayout() { + repeat(2) { + binding.tabLayout.addTab(binding.tabLayout.newTab()) + } + } + + companion object { + private val MYTITLE = listOf("PIE CHART", "LINE CHART") + val myData = loadData() + + fun loadData(): List { + val gson = Gson() + val type = object : TypeToken>() {}.type + MyApp.myResource.reset() + val myJson = MyApp.myResource.bufferedReader(Charset.defaultCharset()) + return gson.fromJson(myJson, type) + } } } \ No newline at end of file diff --git a/app/src/main/java/otus/homework/customview/Tab1Fragment.kt b/app/src/main/java/otus/homework/customview/Tab1Fragment.kt new file mode 100644 index 00000000..a056480b --- /dev/null +++ b/app/src/main/java/otus/homework/customview/Tab1Fragment.kt @@ -0,0 +1,33 @@ +package otus.homework.customview + +import android.net.Uri +import android.os.Bundle +import android.view.View +import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels +import otus.homework.customview.databinding.FragmentTab1Binding +import otus.homework.customview.piechart.ChartModel + +class Tab1Fragment : Fragment(R.layout.fragment_tab1) { + val chartModel: ChartModel by viewModels() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val binding = FragmentTab1Binding.bind(view) + binding.chartView.chartModel = chartModel + + val touchDown = binding.chartView._clickSector + touchDown.observe(viewLifecycleOwner, { + chartModel.setChecked(it) + chartModel.setScale(it) + binding.chartView.invalidate() + }) + } + + interface OnFragmentInteractionListener { + fun onFragmentInteraction(uri: Uri) + } +} \ No newline at end of file diff --git a/app/src/main/java/otus/homework/customview/Tab2Fragment.kt b/app/src/main/java/otus/homework/customview/Tab2Fragment.kt new file mode 100644 index 00000000..72ef958d --- /dev/null +++ b/app/src/main/java/otus/homework/customview/Tab2Fragment.kt @@ -0,0 +1,26 @@ +package otus.homework.customview + +import android.net.Uri +import android.os.Bundle +import android.view.View +import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels +import otus.homework.customview.databinding.FragmentTab2Binding + +class Tab2Fragment : Fragment(R.layout.fragment_tab2) { + val chartModel: LineChartModel by viewModels() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val binding = FragmentTab2Binding.bind(view) + binding.chartView.lineChartModel = chartModel + + } + + interface OnFragmentInteractionListener { + fun onFragmentInteraction(uri: Uri) + } +} \ No newline at end of file diff --git a/app/src/main/java/otus/homework/customview/TabPagerAdapter.kt b/app/src/main/java/otus/homework/customview/TabPagerAdapter.kt new file mode 100644 index 00000000..10e009af --- /dev/null +++ b/app/src/main/java/otus/homework/customview/TabPagerAdapter.kt @@ -0,0 +1,22 @@ +package otus.homework.customview + +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentActivity +import androidx.viewpager2.adapter.FragmentStateAdapter + +class TabPagerAdapter( + fa: FragmentActivity, + private var tabCount: Int +) : FragmentStateAdapter(fa) { + override fun createFragment(position: Int): Fragment { + return when (position) { + 0 -> Tab1Fragment() + 1 -> Tab2Fragment() + else -> Tab1Fragment() + } + } + + override fun getItemCount(): Int { + return tabCount + } +} \ No newline at end of file diff --git a/app/src/main/java/otus/homework/customview/linechart/LineChartModel.kt b/app/src/main/java/otus/homework/customview/linechart/LineChartModel.kt new file mode 100644 index 00000000..453275e8 --- /dev/null +++ b/app/src/main/java/otus/homework/customview/linechart/LineChartModel.kt @@ -0,0 +1,24 @@ +package otus.homework.customview + +import androidx.lifecycle.ViewModel + +class LineChartModel : ViewModel() { + + var grafData: Map + var maxAmount = 0 + var maxTime = 0L + var minTime = 0L + + init { + + grafData = MainActivity.myData + .groupBy { it.time } + .mapValues { + it.value.map { it.amount } + .fold(0) { summ, time -> summ + time } + } + maxAmount = grafData.maxOf { it.value } + maxTime = grafData.maxOf { it.key } + minTime = grafData.minOf { it.key } + } +} diff --git a/app/src/main/java/otus/homework/customview/linechart/LineChartView.kt b/app/src/main/java/otus/homework/customview/linechart/LineChartView.kt new file mode 100644 index 00000000..27c2f1fc --- /dev/null +++ b/app/src/main/java/otus/homework/customview/linechart/LineChartView.kt @@ -0,0 +1,185 @@ +package otus.homework.customview.linechart + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.PointF +import android.os.Bundle +import android.os.Parcelable +import android.util.AttributeSet +import android.view.GestureDetector +import android.view.MotionEvent +import android.view.View +import android.widget.Toast +import otus.homework.customview.LineChartModel +import java.text.SimpleDateFormat +import java.util.* + +class LineChartView : View { + constructor(context: Context?) : super(context) + constructor(context: Context?, attributeSet: AttributeSet?) : super(context, attributeSet) + + companion object { + private const val AXIS_X_DIVIDER = 10 + private const val AXIS_Y_DIVIDER = 10 + } + + var lineChartModel = LineChartModel() + + private val gestureDetector = GestureDetector(context, TouchView()) + private val pChart = Paint() + private val pPoint = Paint() + + + private var startX = 0f + private var startY = 0f + private var stopX = 0f + private var stopY = 0f + private var scaleTime = 1f + private var scaleAmount = 1f + private var timeWidth = 0L + private var lineDX = 0f + private var lineDY = 0f + private var graf: MutableList = mutableListOf() + private var startPoint = PointF(startX, stopY) + private var currentPoint = PointF(0f, 0f) + + init { + isSaveEnabled = true + pChart.isAntiAlias = true + pChart.style = Paint.Style.FILL + pChart.setColor(Color.WHITE) + + pPoint.style = Paint.Style.FILL_AND_STROKE + pPoint.setStrokeWidth(20f) + pPoint.color = Color.BLUE + timeWidth = lineChartModel.maxTime - lineChartModel.minTime + + } + + override fun onSaveInstanceState(): Parcelable { + val bundle = Bundle() + bundle.putParcelable("superState", super.onSaveInstanceState()) + return bundle + } + + override fun onRestoreInstanceState(state: Parcelable?) { + var viewState = state + if (viewState is Bundle) { + viewState = viewState.getParcelable("superState") + } + super.onRestoreInstanceState(viewState) + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + val finalWidth = (getMeasuredWidth() * 0.9).toInt() + val finalHeight = (getMeasuredHeight() * 0.9).toInt() + System.out.println("finalWidth $finalWidth finalHeight $finalHeight") + setMeasuredDimension(finalWidth, finalHeight) + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + startX = width * 0.15f + startY = 0f + stopX = width.toFloat() + stopY = height * 0.9f + lineDX = (stopX - startX) / AXIS_X_DIVIDER + lineDY = (stopY - startY) / AXIS_Y_DIVIDER + scaleTime = if (timeWidth > 0L) + (stopX - startX) / timeWidth + else + (stopX - startX) / 2.0f + + try { + scaleAmount = (stopY - startY) / lineChartModel.maxAmount + } catch (e: NullPointerException) { + Toast.makeText(context, "Нет данных ", Toast.LENGTH_LONG).show() + scaleAmount = 0f + } + + lineChartModel.grafData.forEach { t, u -> + System.out.println("t ${convertLongToTime(t)} u $u") + graf.add(PointF((t - lineChartModel.minTime) * scaleTime, u * scaleAmount)) + } + +// Шаблон + canvas.drawARGB(230, 240, 215, 205) + canvas.drawRect(startX, startY, stopX, stopY, pChart) +// Область графика + pChart.style = Paint.Style.STROKE + pChart.strokeWidth = 5f + pChart.setColor(Color.BLACK) + pChart.textSize = 30f + + canvas.drawRect(startX, startY, stopX, stopY, pChart) +// Сетка осей + for (i: Int in 1..AXIS_X_DIVIDER) { + canvas.drawLine((startX + lineDX * i), startY, (startX + lineDX * i), stopY, pChart) + } + for (i: Int in 1..AXIS_Y_DIVIDER) { + canvas.drawLine(startX, (startY + lineDY * i), stopX, (startY + lineDY * i), pChart) + } +// Пределы значений по Y + canvas.drawText( + "0", + startX - pChart.textSize, + stopY, + pChart + ) + canvas.drawText( + lineChartModel.maxAmount.toString(), + startX - (lineChartModel.maxAmount.toString().length - 1) * pChart.textSize, + startY + 30f, pChart + ) + +// Пределы значений по X + val startTime = convertLongToTime(lineChartModel.minTime) + val stopTime = convertLongToTime(lineChartModel.maxTime) + canvas.drawText(startTime, + startX, + stopY + pChart.textSize, + pChart + ) + canvas.drawText( + stopTime, + stopX - (stopTime.length- 7) * pChart.textSize, + stopY + pChart.textSize, + pChart + ) + System.out.println(" textSize ${lineChartModel.maxAmount.toString().length}") +// Построение графика + pChart.setColor(Color.RED) + graf.forEachIndexed() { index, it -> + System.out.println(" $it") + currentPoint = PointF(startX + it.x, stopY - it.y) + if (index > 0) { + canvas.drawLine( + startPoint.x, startPoint.y, + currentPoint.x, currentPoint.y, + pChart + ) + } + canvas.drawPoint(currentPoint.x, currentPoint.y, pPoint) + startPoint = PointF(currentPoint.x, currentPoint.y) + } + + + } + + override fun onTouchEvent(event: MotionEvent): Boolean { + gestureDetector.onTouchEvent(event) + + return super.onTouchEvent(event) + } + + fun convertLongToTime(time: Long): String { + val date = Date(time) + val format = SimpleDateFormat("MM.dd HH:mm:ss") + return format.format(date) + } + + +} \ No newline at end of file diff --git a/app/src/main/java/otus/homework/customview/TouchView.kt b/app/src/main/java/otus/homework/customview/linechart/TouchView.kt similarity index 83% rename from app/src/main/java/otus/homework/customview/TouchView.kt rename to app/src/main/java/otus/homework/customview/linechart/TouchView.kt index fa13c269..d8fed3e4 100644 --- a/app/src/main/java/otus/homework/customview/TouchView.kt +++ b/app/src/main/java/otus/homework/customview/linechart/TouchView.kt @@ -1,4 +1,4 @@ -package otus.homework.customview +package otus.homework.customview.linechart import android.view.GestureDetector import android.view.MotionEvent diff --git a/app/src/main/java/otus/homework/customview/ChartModel.kt b/app/src/main/java/otus/homework/customview/piechart/ChartModel.kt similarity index 74% rename from app/src/main/java/otus/homework/customview/ChartModel.kt rename to app/src/main/java/otus/homework/customview/piechart/ChartModel.kt index 5f9ca7f6..a36ed2a9 100644 --- a/app/src/main/java/otus/homework/customview/ChartModel.kt +++ b/app/src/main/java/otus/homework/customview/piechart/ChartModel.kt @@ -1,10 +1,14 @@ -package otus.homework.customview +package otus.homework.customview.piechart import androidx.lifecycle.ViewModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken +import otus.homework.customview.MainActivity import otus.homework.customview.MyApp.Companion.myResource +import otus.homework.customview.PayLoad import java.nio.charset.Charset +import java.util.* +import java.util.Collections.emptyList class ChartModel : ViewModel() { @@ -14,14 +18,12 @@ class ChartModel : ViewModel() { var scaleArc: List var checkedIndex: Int = -1 private val sumData: Int - private val myData: List private var startAngle = 0f private var sweepAngle = 0f init { - myData = loadData() - pieData = grafData() - sumData = pieData.map { it -> it.value }.sum() + pieData = pieGrafData() + sumData = pieData.map{it.value}.sum() pieData.forEach { _, i -> beginArc.add(startAngle) sweepAngle = (i * 360f) / sumData @@ -29,10 +31,11 @@ class ChartModel : ViewModel() { System.out.println("startAngle $startAngle") startAngle += sweepAngle } - scaleArc = pieData.map { _ -> 1.0f } + scaleArc = emptyList() + scaleArc = pieData.map {_ -> 1.0f} } - fun grafData() = myData.groupingBy { it.category } + fun pieGrafData() = MainActivity.myData.groupingBy {it.category } .fold(0) { summ, category -> summ + category.amount } fun loadData(): List { @@ -44,7 +47,7 @@ class ChartModel : ViewModel() { } fun setScale(sector: Int) { - scaleArc = scaleArc.mapIndexed { index, scale -> + scaleArc = scaleArc.mapIndexed { index, _ -> if (index == sector) 1.05f else diff --git a/app/src/main/java/otus/homework/customview/MyChartView.kt b/app/src/main/java/otus/homework/customview/piechart/PieChartView.kt similarity index 74% rename from app/src/main/java/otus/homework/customview/MyChartView.kt rename to app/src/main/java/otus/homework/customview/piechart/PieChartView.kt index e7dadd68..9519243a 100644 --- a/app/src/main/java/otus/homework/customview/MyChartView.kt +++ b/app/src/main/java/otus/homework/customview/piechart/PieChartView.kt @@ -1,4 +1,4 @@ -package otus.homework.customview +package otus.homework.customview.piechart import android.content.Context import android.graphics.* @@ -9,13 +9,16 @@ import android.view.GestureDetector import android.view.MotionEvent import android.view.View import androidx.lifecycle.MutableLiveData +import otus.homework.customview.piechart.ChartModel +import otus.homework.customview.piechart.TouchView import kotlin.math.pow -class MyChartView : View { +class PieChartView : View { constructor(context: Context?) : super(context) constructor(context: Context?, attributeSet: AttributeSet?) : super(context, attributeSet) var chartModel = ChartModel() + lateinit var cycleCenter: PointF var _clickSector = MutableLiveData(-1) @@ -68,8 +71,9 @@ class MyChartView : View { override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) - val finalWidth = getMeasuredWidth() * 3 / 4 - val finalHeight = getMeasuredWidth() * 3 / 4 + val size = Math.min(getMeasuredWidth(), getMeasuredHeight()) + val finalWidth = size + val finalHeight = size System.out.println("finalWidth $finalWidth finalHeight $finalHeight") setMeasuredDimension(finalWidth, finalHeight) } @@ -81,36 +85,35 @@ class MyChartView : View { startLeft = width * 0.1f startTop = height * 0.1f // Шаблон - canvas.drawARGB(230, 400, 150, 50) + canvas.drawARGB(230, 400, 150, 50) // Сдвиг для правильного отображения в landscape - canvas.translate(0f, height / 4f) + canvas.translate(0f, height / 4f) // Рисование pieChart - cycleCenter = - PointF((midWidth + startLeft) / 2, (midHeight + startLeft) / 2 + height / 4f) - var j = 0 + cycleCenter = + PointF((midWidth + startLeft) / 2, (midHeight + startLeft) / 2 + height / 4f) + var j = 0 - chartModel.pieData.forEach { s, _ -> - pChart.color = color[j % color.size] - canvas.drawArc( - startLeft - midWidth * (chartModel.scaleArc[j] - 1f), - startTop - midHeight * (chartModel.scaleArc[j] - 1f), - midWidth * chartModel.scaleArc[j], - midHeight * chartModel.scaleArc[j], - chartModel.beginArc.get(j), chartModel.lengthArc.get(j), - false, - pChart - ) + chartModel.pieData.forEach { s, _ -> + pChart.color = color[j % color.size] + canvas.drawArc( + startLeft - midWidth * (chartModel.scaleArc[j] - 1f), + startTop - midHeight * (chartModel.scaleArc[j] - 1f), + midWidth * chartModel.scaleArc[j], + midHeight * chartModel.scaleArc[j], + chartModel.beginArc.get(j), chartModel.lengthArc.get(j), + false, + pChart + ) // В таблицу наименований - canvas.translate(midWidth * 1.2f, j * 50f) - if(j == chartModel.checkedIndex ){ - textDraw(canvas, pText, pChart, s+" !!") - } - else{ - textDraw(canvas, pText, pChart, s)} - - canvas.translate(-midWidth * 1.2f, -j * 50f) - j++ + canvas.translate(midWidth * 1.2f, j * 50f) + if (j == chartModel.checkedIndex) { + textDraw(canvas, pText, pChart, s + " !!") + } else { + textDraw(canvas, pText, pChart, s) } + canvas.translate(-midWidth * 1.2f, -j * 50f) + j++ + } } private fun textDraw(canvas: Canvas, p: Paint, pBack: Paint, text: String) { diff --git a/app/src/main/java/otus/homework/customview/piechart/TouchView.kt b/app/src/main/java/otus/homework/customview/piechart/TouchView.kt new file mode 100644 index 00000000..e8331215 --- /dev/null +++ b/app/src/main/java/otus/homework/customview/piechart/TouchView.kt @@ -0,0 +1,10 @@ +package otus.homework.customview.piechart + +import android.view.GestureDetector +import android.view.MotionEvent + +class TouchView : GestureDetector.SimpleOnGestureListener() { + override fun onDown(e: MotionEvent): Boolean { + return super.onDown(e) + } +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 12e396c0..37e1f577 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -5,17 +5,38 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_gravity="center" - tools:context=".MainActivity"> + tools:context="otus.homework.customview.MainActivity"> - + + + + + + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + /> \ No newline at end of file diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml new file mode 100644 index 00000000..e416e1c1 --- /dev/null +++ b/app/src/main/res/layout/content_main.xml @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_tab1.xml b/app/src/main/res/layout/fragment_tab1.xml new file mode 100644 index 00000000..0bdf898c --- /dev/null +++ b/app/src/main/res/layout/fragment_tab1.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_tab2.xml b/app/src/main/res/layout/fragment_tab2.xml new file mode 100644 index 00000000..ad34a718 --- /dev/null +++ b/app/src/main/res/layout/fragment_tab2.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9213c339..3f4437da 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,6 @@ Custom View + Line Chart + Pie Chart + Tab 1 Fragment \ No newline at end of file diff --git a/build.gradle b/build.gradle index fdd4bb43..0035d82a 100644 --- a/build.gradle +++ b/build.gradle @@ -1,25 +1,17 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = "1.8.0" + ext.kotlin_version = '1.7.1' repositories { google() mavenCentral() - } - dependencies { - classpath 'com.android.tools.build:gradle:7.2.2' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + }} - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } +plugins { + id 'com.android.application' version '7.2.2' apply false + id 'com.android.library' version '7.2.2' apply false + id 'org.jetbrains.kotlin.android' version '1.7.0' apply false } -allprojects { - repositories { - google() - mavenCentral() - } -} task clean(type: Delete) { delete rootProject.buildDir diff --git a/gradle.properties b/gradle.properties index 98bed167..ca36a32b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,4 +18,5 @@ android.useAndroidX=true # Automatically convert third-party libraries to use AndroidX android.enableJetifier=true # Kotlin code style for this project: "official" or "obsolete": -kotlin.code.style=official \ No newline at end of file +kotlin.code.style=official +org.gradle.unsafe.configuration-cache=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e49965f7..1f5a55ab 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Jun 11 17:42:46 MSK 2021 +#Wed Nov 29 17:50:58 CET 2023 distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip +zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle b/settings.gradle index 8eeb99dc..014e7b30 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,16 @@ +pluginManagement { + repositories { + gradlePluginPortal() + google() + mavenCentral() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} include ':app' rootProject.name = "Custom View" \ No newline at end of file