diff --git a/app/build.gradle b/app/build.gradle index b4711913..b81e773e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,16 +1,16 @@ plugins { - id 'com.android.application' - id 'kotlin-android' + alias(libs.plugins.androidApplication) + alias(libs.plugins.kotlinAndroid) } android { - compileSdkVersion 30 - buildToolsVersion "30.0.3" + namespace 'otus.homework.canvas' + compileSdk 33 defaultConfig { - applicationId "otus.homework.customview" - minSdkVersion 23 - targetSdkVersion 30 + applicationId "otus.homework.canvas" + minSdk 24 + targetSdk 33 versionCode 1 versionName "1.0" @@ -34,12 +34,12 @@ 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' - testImplementation 'junit:junit:4.+' - androidTestImplementation 'androidx.test.ext:junit:1.1.2' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + implementation libs.core.ktx + implementation libs.appcompat + implementation libs.material + implementation libs.constraintlayout + testImplementation libs.junit + androidTestImplementation libs.androidx.test.ext.junit + androidTestImplementation libs.espresso.core + implementation libs.gson } \ No newline at end of file diff --git a/app/src/androidTest/java/otus/homework/customview/ExampleInstrumentedTest.kt b/app/src/androidTest/java/otus/homework/canvas/ExampleInstrumentedTest.kt similarity index 84% rename from app/src/androidTest/java/otus/homework/customview/ExampleInstrumentedTest.kt rename to app/src/androidTest/java/otus/homework/canvas/ExampleInstrumentedTest.kt index d5e3dba4..25847539 100644 --- a/app/src/androidTest/java/otus/homework/customview/ExampleInstrumentedTest.kt +++ b/app/src/androidTest/java/otus/homework/canvas/ExampleInstrumentedTest.kt @@ -1,4 +1,4 @@ -package otus.homework.customview +package otus.homework.canvas import androidx.test.platform.app.InstrumentationRegistry import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -19,6 +19,6 @@ class ExampleInstrumentedTest { fun useAppContext() { // Context of the app under test. val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("otus.homework.customview", appContext.packageName) + assertEquals("otus.homework.canvas", appContext.packageName) } } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index efd1e519..ea6f0b25 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,19 +1,23 @@ - + + - + android:theme="@style/Theme.HW_Canvas" + tools:targetApi="31"> + - diff --git a/app/src/main/java/otus/homework/canvas/JsonData.kt b/app/src/main/java/otus/homework/canvas/JsonData.kt new file mode 100644 index 00000000..026f3881 --- /dev/null +++ b/app/src/main/java/otus/homework/canvas/JsonData.kt @@ -0,0 +1,71 @@ +import android.content.Context +import com.google.gson.Gson +import com.google.gson.annotations.SerializedName +import com.google.gson.reflect.TypeToken +import otus.homework.canvas.LineGraphData +import otus.homework.canvas.PieChartSectorData +import otus.homework.canvas.R +import java.text.SimpleDateFormat + +class JsonData(private val context: Context) { + + data class JsonData( + val id: Int, + val name: String, + val amount: Int, + val category: String, + val time: Int + ) + + fun getJsonData(): List? { + try { + val jsonFile = context.resources.openRawResource(R.raw.payload).bufferedReader() + val arrayTutorialType = object : TypeToken>() {}.type + val purchases = Gson().fromJson>(jsonFile, arrayTutorialType) + return purchases + } catch (error: Exception) { + return null + } + } + + fun getPieChartSectorData(): List? { + val jsonDataArray = getJsonData() ?: return null + val pieChartSectorDataMap = mutableMapOf() + for (data in jsonDataArray) { + if (pieChartSectorDataMap.containsKey(data.category)) { + pieChartSectorDataMap[data.category]?.angle = pieChartSectorDataMap[data.category]?.angle!! + data.amount.toFloat() + } + else { + pieChartSectorDataMap += data.category to + PieChartSectorData( + angle = data.amount.toFloat(), + text = data.category, + category = data.category + ) + } + } + val pieChartSectorData = mutableListOf() + for ((key, value) in pieChartSectorDataMap) { + pieChartSectorData += value + } + return pieChartSectorData + } + + + //private fun timeToString_(time: Int) = "$time" // TODO + private fun timeToString(time: Float) = SimpleDateFormat.getDateTimeInstance().format(time.toInt()) + + fun getLineGraphData(): MutableMap>? { + val jsonDataArray = getJsonData() ?: return null + var lineGraphData = mutableMapOf>() + for (data in jsonDataArray) { + val addData = LineGraphData(data.time.toFloat(), data.amount.toFloat(), ::timeToString) + if (lineGraphData.containsKey(data.category)) { + lineGraphData[data.category]!!.add(addData) + } else { + lineGraphData += data.category to mutableListOf(addData) + } + } + return lineGraphData as MutableMap> + } +} diff --git a/app/src/main/java/otus/homework/canvas/LineGraphData.kt b/app/src/main/java/otus/homework/canvas/LineGraphData.kt new file mode 100644 index 00000000..0c2f8c88 --- /dev/null +++ b/app/src/main/java/otus/homework/canvas/LineGraphData.kt @@ -0,0 +1,7 @@ +package otus.homework.canvas + +data class LineGraphData( + val valueX: Float, + val valueY: Float, + val xToString: (Float) -> String = {v -> "$v"} +) diff --git a/app/src/main/java/otus/homework/canvas/LineGraphView.kt b/app/src/main/java/otus/homework/canvas/LineGraphView.kt new file mode 100644 index 00000000..6e970f15 --- /dev/null +++ b/app/src/main/java/otus/homework/canvas/LineGraphView.kt @@ -0,0 +1,169 @@ +package otus.homework.canvas + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Matrix +import android.graphics.Paint +import android.graphics.Path +import android.graphics.Point +import android.graphics.PointF +import android.util.AttributeSet +import android.util.Log +import android.view.MotionEvent +import android.view.ScaleGestureDetector +import android.view.View + + +class LineGraphView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0 +) : View(context, attrs, defStyleAttr) { + + private var myBackgroundColor: Int = Color.rgb(50, 150, 50) // TO_DO xml app:backgroundColor + private var padding = 50F // TO_DO xml app:padding + private var graphData: MutableMap>? = null + private var scale = 1F + private var offset = PointF(0F, 0F) + private var scaleGestureDetector = ScaleGestureDetector(context, MyOnScaleGestureListener()) + private var maxX = 0F + private var minX = 0F + private var maxY = 0F + private var minY = 0F + private val presetColors: IntArray = context.resources.getIntArray(R.array.presetColors) + private val textSize = 35F + private val strokeWidth = 10F + private var touchPosition: PointF? = null + private var touchSavedOffset = PointF(offset.x, offset.y) + + override fun dispatchTouchEvent(event: MotionEvent): Boolean { + scaleGestureDetector.onTouchEvent(event) + return when (event.action) { + MotionEvent.ACTION_DOWN -> { + touchSavedOffset = PointF(offset.x, offset.y) + touchPosition = PointF(event.x, event.y) + Log.d("***[", "touchPosition=$touchPosition") + true + } + MotionEvent.ACTION_MOVE -> { + offset.x = touchSavedOffset.x + event.x - touchPosition!!.x + offset.y = touchSavedOffset.y + event.y - touchPosition!!.y + invalidate(); + Log.d("***[", "offset=$offset touchPosition=$touchPosition" ) + true + } + MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { + touchPosition = null + Log.d("***[", "touchPosition=null") + true + } + else -> { + // TO?DO Нужно обрабатывать евенты 261 и 262 + // Иначе при двойном касании когда первый и последний пальцы разные, дергается offset. + // offset резко меняется на разницу позиций пальцев. Пока TO?DO, хотя может это такая фича, а не бага :) + Log.d("***[", "action=${event.action}") + false + } + } + } + + inner class MyOnScaleGestureListener : ScaleGestureDetector.SimpleOnScaleGestureListener() { + override fun onScale(detector: ScaleGestureDetector): Boolean { + invalidate(); + scale *= detector.scaleFactor + Log.d("***[", "scale=$scale") + return true + } + } + + fun Int.modToString() = when(this) { + MeasureSpec.UNSPECIFIED -> "UNSPECIFIED" + MeasureSpec.EXACTLY->"EXACTLY" + MeasureSpec.AT_MOST->"AT_MOST" + else -> "---" + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + val widthMod = MeasureSpec.getMode(widthMeasureSpec) + val widthSize = MeasureSpec.getSize(widthMeasureSpec) + val heightMod = MeasureSpec.getMode(heightMeasureSpec) + val heightSize = MeasureSpec.getSize(heightMeasureSpec) + //Log.d("***[", "widthMod=${widthMod.modToString()} widthSize=$widthSize heightMod=${heightMod.modToString()} heightSize=$heightSize") + // График подстраивается под размер экрана, по этому size не меняем + setMeasuredDimension(widthSize,heightSize) + } + + fun setData(graphData: MutableMap>?) { + this.graphData = graphData + invalidate() + maxX = 0F + minX = Float.MAX_VALUE + maxY = 0F + minY = Float.MAX_VALUE + offset = PointF(0F, 0F) + scale = 1F + graphData ?.let { + for (g in graphData) { + graphData[g.key] = g.value.sortedBy { it.valueX } + for (d in g.value) { + maxX = maxOf(maxX, d.valueX) + minX = minOf(minX, d.valueX) + maxY = maxOf(maxY, d.valueY) + minY = minOf(minY, d.valueY) + } + } + } + } + + val paint = Paint().apply { + style = Paint.Style.STROKE + textSize = this@LineGraphView.textSize + strokeWidth = strokeWidth + } + + override fun onDrawForeground(canvas: Canvas) { + canvas.apply { + drawColor(myBackgroundColor) + graphData?.let { + var num = 0 + for (d in it) { + showGraph(num++, d.key, d.value) + paint.strokeWidth = 2F + drawText(d.key, padding + 10, padding + 10 + textSize * 1.3F * num, paint) + paint.strokeWidth = strokeWidth + } + } + val path = Path() + path.moveTo(padding, padding) + path.lineTo(padding, height - padding) + path.lineTo(width - padding, height - padding) + paint.color = Color.BLACK + drawPath(path, paint) + } + } + + private fun LineGraphData.getReX() = (valueX.toFloat() - minX) * (width - 2 * padding) / (maxX - minX) + padding + private fun LineGraphData.getReY() = height - ((valueY - minY) * (height- 2 * padding) / (maxY - minY) + padding) + + private fun LineGraphData.log(num: Int) { Log.d("***[", "num=$num XY[$valueX,$valueY] -> [${getReX()} ${getReY()}]") } + + private fun Canvas.showGraph(num: Int, category: String, data: List) { + val path = Path() + if (data.size == 1) { + path.addCircle(data[0].getReX(), data[0].getReY(), 3F, Path.Direction.CW) + } else { + path.moveTo(data[0].getReX(), data[0].getReY()) + //data[0].log(num) + for (i in 1 until data.size) { + //data[i].log(num) + path.lineTo(data[i].getReX(), data[i].getReY()) + } + } + val numColor = num % presetColors.size + paint.color = presetColors[numColor] + val matrix = Matrix() + matrix.setScale(scale, scale) + path.transform(matrix) + path.offset(offset.x, offset.y) + drawPath(path, paint) + } +} \ No newline at end of file diff --git a/app/src/main/java/otus/homework/canvas/LinearAutoChangeLayout.kt b/app/src/main/java/otus/homework/canvas/LinearAutoChangeLayout.kt new file mode 100644 index 00000000..999825dc --- /dev/null +++ b/app/src/main/java/otus/homework/canvas/LinearAutoChangeLayout.kt @@ -0,0 +1,31 @@ +package otus.homework.canvas + +import android.content.Context +import android.content.res.Configuration +import android.content.res.TypedArray +import android.util.AttributeSet +import android.util.Log +import android.widget.LinearLayout + +class LinearAutoChangeLayout @JvmOverloads constructor( + context: Context, private val attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0 +) : LinearLayout(context, attrs, defStyleAttr) { + + private var isVerticalOrientation: Boolean? = null + + init { + val typedArray: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.LinearAutoChangeLayout) + isVerticalOrientation = "vertical" == typedArray.getString(R.styleable.LinearAutoChangeLayout_baseOrientation) + } + + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + val widthSize = MeasureSpec.getSize(widthMeasureSpec) + val heightSize = MeasureSpec.getSize(heightMeasureSpec) + + val isRealyVerticalOrientation: Boolean = resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT + orientation = if (isVerticalOrientation == isRealyVerticalOrientation) VERTICAL else HORIZONTAL + Log.d("***[", "width=$widthSize height=$heightSize $isVerticalOrientation $orientation $isRealyVerticalOrientation") + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + } +} \ No newline at end of file diff --git a/app/src/main/java/otus/homework/canvas/MainActivity.kt b/app/src/main/java/otus/homework/canvas/MainActivity.kt new file mode 100644 index 00000000..83742871 --- /dev/null +++ b/app/src/main/java/otus/homework/canvas/MainActivity.kt @@ -0,0 +1,86 @@ +package otus.homework.canvas + +import JsonData +import android.content.Context +import android.graphics.Color +import android.os.Build +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import android.os.VibrationEffect +import android.os.Vibrator +import android.util.Log +import android.view.View +import kotlin.math.sin + +class MainActivity : AppCompatActivity() { + + val pieChartView: PieChartView by lazy { findViewById(R.id.PieChartView) } + val lineGraphView: LineGraphView by lazy { findViewById(R.id.LineGraphView) } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + //onFull(null) + onMyData(null) + } + + + fun onFull(view: View?) { + val jsonData = JsonData(applicationContext) + pieChartView.setData(jsonData.getPieChartSectorData(), -1F) {category, num -> clickCallBack(category, num)} + lineGraphView.setData(jsonData.getLineGraphData()) + + } + + private fun clickCallBack(category: String, numSector: Int) { + Log.d("***[", "clickCallBack category=$category numSector=$numSector") + val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator + if (Build.VERSION.SDK_INT >= 26) { + vibrator.vibrate( + VibrationEffect.createOneShot( + 200, + VibrationEffect.DEFAULT_AMPLITUDE + ) + ) + } else { + vibrator.vibrate(200) + } + } + + fun onMyData(view: View?) { + val sectors = arrayListOf( + PieChartSectorData(10F, Color.RED, 50F, "10", "Sector №1"), + PieChartSectorData(15F, Color.YELLOW, 40F, "15", "Sector №2"), + PieChartSectorData(7F, Color.GREEN, 45F, "7", "Sector №3"), + PieChartSectorData(18F, Color.BLUE, 52F, "18", "Sector №4"), + ) + pieChartView.setData(sectors, 32F) {category, num -> clickCallBack(category, num)} + + var lineGraphData = mutableMapOf>() + + lineGraphData += "param1" to arrayListOf( + LineGraphData(5F,20F), + LineGraphData(0F,12F), + LineGraphData(4F,33F), + LineGraphData(2F,55F), + LineGraphData(3F,52F), + LineGraphData(1F,40F), + ) + var sinY = arrayListOf() + for (t in 0 .. 500) { + val y = sin(t.toFloat() / 50F) * 50F + sinY.add(LineGraphData(t.toFloat()/100, y)) + } + lineGraphData += "param2" to sinY + lineGraphData += "param3" to arrayListOf( + LineGraphData(5F,00F), + LineGraphData(0F,20F), + LineGraphData(4F,30F), + LineGraphData(2F,60F), + LineGraphData(3F,50F), + LineGraphData(1F,40F), + ) + lineGraphView.setData(lineGraphData) + } +} + diff --git a/app/src/main/java/otus/homework/canvas/PieChartSectorData.kt b/app/src/main/java/otus/homework/canvas/PieChartSectorData.kt new file mode 100644 index 00000000..9a19de72 --- /dev/null +++ b/app/src/main/java/otus/homework/canvas/PieChartSectorData.kt @@ -0,0 +1,10 @@ +package otus.homework.canvas + +data class PieChartSectorData( + var angle: Float, + var color: Int = Int.MAX_VALUE, + val radius: Float = 100F, + val text: String? = null, + val category: String, + var startAngle: Float = 0F, +) diff --git a/app/src/main/java/otus/homework/canvas/PieChartView.kt b/app/src/main/java/otus/homework/canvas/PieChartView.kt new file mode 100644 index 00000000..8c1ccabc --- /dev/null +++ b/app/src/main/java/otus/homework/canvas/PieChartView.kt @@ -0,0 +1,202 @@ +package otus.homework.canvas + +import android.content.Context +import android.content.res.TypedArray +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.Path +import android.graphics.Rect +import android.graphics.RectF +import android.util.AttributeSet +import android.util.Log +import android.view.MotionEvent +import android.view.View +import kotlin.math.PI +import kotlin.math.atan2 +import kotlin.math.sqrt + + +class PieChartView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0 +) : View(context, attrs, defStyleAttr) { + + private var myBackgroundColor: Int = Color.WHITE + private var gap = 0F + private var defaultWidth = 25F + private var startAngle = -90F + private var padding = 20F + private var numPressed: Int? = null + + private var pieChartSectorDataArray: List? = null + private var callback: ((category: String, Int) -> Unit)? = null + private var summaryAngle: Float = 0F + private var minDiameter: Float = 0F + private var maxDiameter: Float = 0F + + init { + val typedArray: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.PieChartView) + myBackgroundColor = typedArray.getColor(R.styleable.PieChartView_backgroundColor, myBackgroundColor) + gap = typedArray.getDimension(R.styleable.PieChartView_defaultGap, gap) + defaultWidth = typedArray.getDimension(R.styleable.PieChartView_defaultWidth, defaultWidth) + startAngle = typedArray.getDimension(R.styleable.PieChartView_startAngle, startAngle) + padding = typedArray.getDimension(R.styleable.PieChartView_padding, padding) + typedArray.recycle() + } + + fun Int.modToString() = when(this) { + MeasureSpec.UNSPECIFIED -> "UNSPECIFIED" + MeasureSpec.EXACTLY->"EXACTLY" + MeasureSpec.AT_MOST->"AT_MOST" + else -> "---" + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + val widthMod = MeasureSpec.getMode(widthMeasureSpec) + val widthSize = MeasureSpec.getSize(widthMeasureSpec) + val heightMod = MeasureSpec.getMode(heightMeasureSpec) + val heightSize = MeasureSpec.getSize(heightMeasureSpec) + //Log.d("***[", "widthMod=${widthMod.modToString()} widthSize=$widthSize heightMod=${heightMod.modToString()} heightSize=$heightSize") + val size = minOf(widthSize,heightSize) + setMeasuredDimension(size,size) // Что бы круг был круглым, а квадрат квадратным :) + } + + fun getNumSector(x: Float, y: Float): Int? { + val diameter: Float = sqrt(x*x + y*y) * 2 + //Log.d("***[", "***2 radius=$radius minRadius=${reCalcSize(minDiameter)} maxRadius=${reCalcSize(maxDiameter)}") + if (diameter < reCalcSize(minDiameter) || diameter > reCalcSize(maxDiameter)) { + return null + } + var angle = atan2(y, x) / (2 * PI) * 360 + angle = if (angle < 0) angle + 360 else angle + + for (num: Int in 0 until pieChartSectorDataArray!!.size) { + val sector = pieChartSectorDataArray!![num] + var startAngle = sector.startAngle + var endAngle = sector.startAngle + sector.angle + if (startAngle < 0 && endAngle < 0) { + startAngle += 360 + endAngle += 360 + } + //Log.d("***[", "angle=$angle startAngle=${startAngle} endAngle=${endAngle}") + if (angle > startAngle && angle < endAngle || + startAngle < 0 && endAngle > 0 && angle > startAngle + 360) { + return num + } + } + return null + } + + override fun dispatchTouchEvent(event: MotionEvent): Boolean { + if (pieChartSectorDataArray == null) { + return false + } + numPressed = + when (event.action) { + MotionEvent.ACTION_DOWN -> { + val displaySize = minOf(width, height).toFloat() + val num = getNumSector(event.x - displaySize / 2, event.y - displaySize / 2) + num?.let { callback?.invoke(pieChartSectorDataArray!![it].category, it) } + num + } + MotionEvent.ACTION_UP -> null + else -> return false + } + return true + } + + fun setData( + pieChartSectorDataArray: List?, + minRadius: Float, + callback: (category: String, Int) -> Unit + ): Boolean { + invalidate() + this.pieChartSectorDataArray = pieChartSectorDataArray + pieChartSectorDataArray ?: return false + this.callback = callback + this.minDiameter = minRadius + // set pre value + var calcMinRadius = Float.MAX_VALUE + summaryAngle = 0F + maxDiameter = 0F + var numColor = 0 + val presetColors: IntArray = context.resources.getIntArray(R.array.presetColors) + // Find max & min + for (sector in pieChartSectorDataArray) { + calcMinRadius = minOf(calcMinRadius, sector.radius) + summaryAngle += sector.angle + maxDiameter = maxOf(maxDiameter, sector.radius) + if (sector.color == Int.MAX_VALUE) { + sector.color = presetColors[numColor++] + } + } + if (minRadius < 0) { + this.minDiameter = calcMinRadius * 3 / 4 + } else if (calcMinRadius < minRadius) { + this.pieChartSectorDataArray = null + return false + } + // + val k = (360 - gap * pieChartSectorDataArray.size) / summaryAngle + var curtrentAngle = startAngle + for (sector in pieChartSectorDataArray) { + sector.angle *= k + sector.startAngle = curtrentAngle + curtrentAngle += sector.angle + gap + } + return true + } + + private fun reCalcSize(size: Float) = size * (minOf(width,height).toFloat() - padding * 2) / maxDiameter + + private fun getRect(diameter: Float): RectF { + val displaySize = minOf(width,height).toFloat() + val calcPadding = (displaySize - reCalcSize(diameter)) / 2 + return RectF(calcPadding, calcPadding, displaySize-calcPadding, displaySize-calcPadding) + } + + val path = Path() + val paint = Paint().apply { + textSize = 30F + textAlign = Paint.Align.CENTER + isAntiAlias = true + } + + override fun onDrawForeground(canvas: Canvas) { + + canvas.apply { + drawColor(myBackgroundColor) + + if (pieChartSectorDataArray == null) { + return + } + + for (sector in pieChartSectorDataArray!!) { + DrawSector(sector) + } + + paint.color = myBackgroundColor + drawArc(getRect(minDiameter), 0F, 360F, true, paint) + } + } + + fun Canvas.DrawSector(sector: PieChartSectorData) { + val rect = getRect(sector.radius) + paint.color = sector.color + drawArc(rect, sector.startAngle, sector.angle, true, paint) + + if (sector.text != null) { + val textRect = Rect() + paint.getTextBounds(sector.text, 0, sector.text.length, textRect) + val height = textRect.height() + + val calcHeight = sector.angle * rect.width() / PI / 100 // TO?DO?changed + if (height < calcHeight) { + paint.color = Color.BLACK + path.reset(); + path.addArc(rect, sector.startAngle, sector.angle) + drawTextOnPath(sector.text, path, 0F, 0F, paint) + } + } + } +} \ 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 deleted file mode 100644 index 78cb9448..00000000 --- a/app/src/main/java/otus/homework/customview/MainActivity.kt +++ /dev/null @@ -1,11 +0,0 @@ -package otus.homework.customview - -import androidx.appcompat.app.AppCompatActivity -import android.os.Bundle - -class MainActivity : AppCompatActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) - } -} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml index 74852f7d..07d5da9c 100644 --- a/app/src/main/res/drawable/ic_launcher_background.xml +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -1,171 +1,170 @@ - + android:viewportHeight="108"> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> + android:strokeWidth="0.8" + android:strokeColor="#33FFFFFF" /> diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml similarity index 87% rename from app/src/main/res/drawable-v24/ic_launcher_foreground.xml rename to app/src/main/res/drawable/ic_launcher_foreground.xml index 7361bc1a..2b068d11 100644 --- a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -1,10 +1,9 @@ - + android:viewportHeight="108"> + android:strokeWidth="1" + android:strokeColor="#00000000" /> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 79ae6993..3ccb99c2 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,19 +1,45 @@ - - + + + android:orientation="horizontal" + app:baseOrientation="horizontal"> +