fix: Show correct trending tag values at the end of the chart lines (#380)
The previous code incorrectly showed the trending tag usage data twice next to the end of the trending tag lines, instead of one entry for the usage data and one entry for the account data. Fix that. As part of this fix change how the data is displayed. Instead of using two distinct `TextView`, fixed to the bottom end of the chart, draw the text directly on the chart. The text is accurately position so that it is next to the end of the relevant line. If both lines overlap the label positions are adjusted appropriately. The chart now uses Pachli blue and orange for the line colours. While doing this I discovered that the mechanism used to fall back to particular chart colours if none were specified was incorrect, so fix that too.
This commit is contained in:
parent
bdb3a61523
commit
dcc2954148
|
@ -1433,7 +1433,7 @@
|
|||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/values/colors.xml"
|
||||
line="101"
|
||||
line="105"
|
||||
column="12"/>
|
||||
</issue>
|
||||
|
||||
|
@ -1444,7 +1444,7 @@
|
|||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/values/colors.xml"
|
||||
line="102"
|
||||
line="106"
|
||||
column="12"/>
|
||||
</issue>
|
||||
|
||||
|
@ -2027,7 +2027,7 @@
|
|||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/values/styles.xml"
|
||||
line="127"
|
||||
line="129"
|
||||
column="12"/>
|
||||
</issue>
|
||||
|
||||
|
@ -2038,7 +2038,7 @@
|
|||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/values/styles.xml"
|
||||
line="165"
|
||||
line="173"
|
||||
column="12"/>
|
||||
</issue>
|
||||
|
||||
|
@ -4788,50 +4788,6 @@
|
|||
column="2"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="SelectableText"
|
||||
message="Consider making the text value selectable by specifying `android:textIsSelectable="true"`"
|
||||
errorLine1=" <TextView"
|
||||
errorLine2=" ~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout-land/item_trending_cell.xml"
|
||||
line="33"
|
||||
column="6"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="SelectableText"
|
||||
message="Consider making the text value selectable by specifying `android:textIsSelectable="true"`"
|
||||
errorLine1=" <TextView"
|
||||
errorLine2=" ~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout/item_trending_cell.xml"
|
||||
line="33"
|
||||
column="6"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="SelectableText"
|
||||
message="Consider making the text value selectable by specifying `android:textIsSelectable="true"`"
|
||||
errorLine1=" <TextView"
|
||||
errorLine2=" ~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout-land/item_trending_cell.xml"
|
||||
line="50"
|
||||
column="6"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="SelectableText"
|
||||
message="Consider making the text value selectable by specifying `android:textIsSelectable="true"`"
|
||||
errorLine1=" <TextView"
|
||||
errorLine2=" ~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout/item_trending_cell.xml"
|
||||
line="50"
|
||||
column="6"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="SelectableText"
|
||||
message="Consider making the text value selectable by specifying `android:textIsSelectable="true"`"
|
||||
|
@ -4839,7 +4795,7 @@
|
|||
errorLine2=" ~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout-land/item_trending_cell.xml"
|
||||
line="79"
|
||||
line="41"
|
||||
column="10"/>
|
||||
</issue>
|
||||
|
||||
|
@ -4850,7 +4806,7 @@
|
|||
errorLine2=" ~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout/item_trending_cell.xml"
|
||||
line="79"
|
||||
line="41"
|
||||
column="10"/>
|
||||
</issue>
|
||||
|
||||
|
@ -4861,7 +4817,7 @@
|
|||
errorLine2=" ~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout-land/item_trending_cell.xml"
|
||||
line="94"
|
||||
line="56"
|
||||
column="10"/>
|
||||
</issue>
|
||||
|
||||
|
@ -4872,7 +4828,7 @@
|
|||
errorLine2=" ~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout/item_trending_cell.xml"
|
||||
line="94"
|
||||
line="56"
|
||||
column="10"/>
|
||||
</issue>
|
||||
|
||||
|
@ -4883,7 +4839,7 @@
|
|||
errorLine2=" ~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout-land/item_trending_cell.xml"
|
||||
line="125"
|
||||
line="87"
|
||||
column="10"/>
|
||||
</issue>
|
||||
|
||||
|
@ -4894,7 +4850,7 @@
|
|||
errorLine2=" ~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout/item_trending_cell.xml"
|
||||
line="126"
|
||||
line="88"
|
||||
column="10"/>
|
||||
</issue>
|
||||
|
||||
|
@ -4986,50 +4942,6 @@
|
|||
column="9"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="SmallSp"
|
||||
message="Avoid using sizes smaller than `11sp`: `8sp`"
|
||||
errorLine1=" android:textSize="8sp""
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout-land/item_trending_cell.xml"
|
||||
line="42"
|
||||
column="9"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="SmallSp"
|
||||
message="Avoid using sizes smaller than `11sp`: `8sp`"
|
||||
errorLine1=" android:textSize="8sp""
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout/item_trending_cell.xml"
|
||||
line="42"
|
||||
column="9"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="SmallSp"
|
||||
message="Avoid using sizes smaller than `11sp`: `8sp`"
|
||||
errorLine1=" android:textSize="8sp""
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout-land/item_trending_cell.xml"
|
||||
line="59"
|
||||
column="9"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="SmallSp"
|
||||
message="Avoid using sizes smaller than `11sp`: `8sp`"
|
||||
errorLine1=" android:textSize="8sp""
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout/item_trending_cell.xml"
|
||||
line="59"
|
||||
column="9"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="Autofill"
|
||||
message="Missing `autofillHints` attribute"
|
||||
|
@ -5184,50 +5096,6 @@
|
|||
column="9"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="RtlSymmetry"
|
||||
message="When you define `paddingStart` you should probably also define `paddingEnd` for right-to-left symmetry"
|
||||
errorLine1=" android:paddingStart="6dp""
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout-land/item_trending_cell.xml"
|
||||
line="38"
|
||||
column="9"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="RtlSymmetry"
|
||||
message="When you define `paddingStart` you should probably also define `paddingEnd` for right-to-left symmetry"
|
||||
errorLine1=" android:paddingStart="6dp""
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout/item_trending_cell.xml"
|
||||
line="38"
|
||||
column="9"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="RtlSymmetry"
|
||||
message="When you define `paddingStart` you should probably also define `paddingEnd` for right-to-left symmetry"
|
||||
errorLine1=" android:paddingStart="6dp""
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout-land/item_trending_cell.xml"
|
||||
line="55"
|
||||
column="9"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="RtlSymmetry"
|
||||
message="When you define `paddingStart` you should probably also define `paddingEnd` for right-to-left symmetry"
|
||||
errorLine1=" android:paddingStart="6dp""
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout/item_trending_cell.xml"
|
||||
line="55"
|
||||
column="9"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="RtlSymmetry"
|
||||
message="When you define `paddingStart` you should probably also define `paddingEnd` for right-to-left symmetry"
|
||||
|
|
|
@ -41,9 +41,6 @@ class TrendingTagViewHolder(
|
|||
val totalAccounts = tagViewData.accounts.sum()
|
||||
binding.totalAccounts.text = formatNumber(totalAccounts, 1000)
|
||||
|
||||
binding.currentUsage.text = tagViewData.usage.last().toString()
|
||||
binding.currentAccounts.text = tagViewData.usage.last().toString()
|
||||
|
||||
itemView.setOnClickListener {
|
||||
onViewTag(tagViewData.name)
|
||||
}
|
||||
|
|
|
@ -26,15 +26,18 @@ import android.util.AttributeSet
|
|||
import android.view.View
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.annotation.Dimension
|
||||
import androidx.core.content.res.use
|
||||
import androidx.core.content.withStyledAttributes
|
||||
import androidx.core.util.TypedValueCompat.dpToPx
|
||||
import app.pachli.R
|
||||
import app.pachli.core.common.util.formatNumber
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import kotlin.math.max
|
||||
|
||||
class GraphView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0,
|
||||
) : View(context, attrs, defStyleAttr) {
|
||||
defStyleAttr: Int = R.attr.graphViewStyle,
|
||||
) : View(context, attrs, defStyleAttr, R.style.Pachli_Widget_GraphView) {
|
||||
@get:ColorInt
|
||||
@ColorInt
|
||||
var primaryLineColor = 0
|
||||
|
@ -56,12 +59,17 @@ class GraphView @JvmOverloads constructor(
|
|||
|
||||
private var proportionalTrending = false
|
||||
|
||||
private lateinit var primaryLinePaint: Paint
|
||||
private lateinit var secondaryLinePaint: Paint
|
||||
private lateinit var primaryCirclePaint: Paint
|
||||
private lateinit var secondaryCirclePaint: Paint
|
||||
private lateinit var graphPaint: Paint
|
||||
private lateinit var metaPaint: Paint
|
||||
private val primaryLinePaint: Paint
|
||||
private val secondaryLinePaint: Paint
|
||||
private val primaryCirclePaint: Paint
|
||||
private val secondaryCirclePaint: Paint
|
||||
private val primaryTextPaint: Paint
|
||||
private val secondaryTextPaint: Paint
|
||||
private var labelTextSize: Float = dpToPx(11f, context.resources.displayMetrics)
|
||||
private val graphPaint: Paint
|
||||
private val metaPaint: Paint
|
||||
|
||||
private var paddingEnd: Float = 0f
|
||||
|
||||
private lateinit var sizeRect: Rect
|
||||
private var primaryLinePath: Path = Path()
|
||||
|
@ -69,25 +77,9 @@ class GraphView @JvmOverloads constructor(
|
|||
|
||||
var maxTrendingValue: Long = 300
|
||||
var primaryLineData: List<Long> = if (isInEditMode) {
|
||||
listOf(
|
||||
30,
|
||||
60,
|
||||
70,
|
||||
80,
|
||||
130,
|
||||
190,
|
||||
80,
|
||||
)
|
||||
listOf(30, 60, 70, 80, 130, 190, 80)
|
||||
} else {
|
||||
listOf(
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
)
|
||||
listOf(1, 1, 1, 1, 1, 1, 1)
|
||||
}
|
||||
set(value) {
|
||||
field = value.map { max(1, it) }
|
||||
|
@ -96,25 +88,9 @@ class GraphView @JvmOverloads constructor(
|
|||
}
|
||||
|
||||
var secondaryLineData: List<Long> = if (isInEditMode) {
|
||||
listOf(
|
||||
10,
|
||||
20,
|
||||
40,
|
||||
60,
|
||||
100,
|
||||
132,
|
||||
20,
|
||||
)
|
||||
listOf(10, 20, 40, 60, 100, 132, 20)
|
||||
} else {
|
||||
listOf(
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
)
|
||||
listOf(1, 1, 1, 1, 1, 1, 1)
|
||||
}
|
||||
set(value) {
|
||||
field = value.map { max(1, it) }
|
||||
|
@ -123,48 +99,41 @@ class GraphView @JvmOverloads constructor(
|
|||
}
|
||||
|
||||
init {
|
||||
initFromXML(attrs)
|
||||
}
|
||||
|
||||
private fun initFromXML(attr: AttributeSet?) {
|
||||
context.obtainStyledAttributes(attr, R.styleable.GraphView).use { a ->
|
||||
primaryLineColor = context.getColor(
|
||||
a.getResourceId(
|
||||
R.styleable.GraphView_primaryLineColor,
|
||||
R.color.tusky_blue,
|
||||
),
|
||||
context.withStyledAttributes(attrs, R.styleable.GraphView, defStyleAttr, R.style.Pachli_Widget_GraphView) {
|
||||
primaryLineColor = getColor(
|
||||
R.styleable.GraphView_primaryLineColor,
|
||||
MaterialColors.getColor(this@GraphView, com.google.android.material.R.attr.colorPrimary),
|
||||
)
|
||||
|
||||
secondaryLineColor = context.getColor(
|
||||
a.getResourceId(
|
||||
R.styleable.GraphView_secondaryLineColor,
|
||||
R.color.tusky_red,
|
||||
),
|
||||
secondaryLineColor = getColor(
|
||||
R.styleable.GraphView_secondaryLineColor,
|
||||
MaterialColors.getColor(this@GraphView, com.google.android.material.R.attr.colorSecondary),
|
||||
)
|
||||
|
||||
lineWidth = a.getDimensionPixelSize(
|
||||
metaColor = getColor(
|
||||
R.styleable.GraphView_metaColor,
|
||||
MaterialColors.getColor(this@GraphView, com.google.android.material.R.attr.colorOutline),
|
||||
)
|
||||
|
||||
lineWidth = getDimensionPixelSize(
|
||||
R.styleable.GraphView_lineWidth,
|
||||
R.dimen.graph_line_thickness,
|
||||
).toFloat()
|
||||
|
||||
graphColor = context.getColor(
|
||||
a.getResourceId(
|
||||
R.styleable.GraphView_graphColor,
|
||||
android.R.attr.colorBackground,
|
||||
),
|
||||
graphColor = getColor(
|
||||
R.styleable.GraphView_graphColor,
|
||||
MaterialColors.getColor(this@GraphView, android.R.attr.colorBackground),
|
||||
)
|
||||
|
||||
metaColor = context.getColor(
|
||||
a.getResourceId(
|
||||
R.styleable.GraphView_metaColor,
|
||||
com.google.android.material.R.attr.dividerColor,
|
||||
),
|
||||
)
|
||||
|
||||
proportionalTrending = a.getBoolean(
|
||||
proportionalTrending = getBoolean(
|
||||
R.styleable.GraphView_proportionalTrending,
|
||||
proportionalTrending,
|
||||
)
|
||||
|
||||
labelTextSize = getDimensionPixelSize(
|
||||
R.styleable.GraphView_labelTextSize,
|
||||
labelTextSize.toInt(),
|
||||
).toFloat()
|
||||
}
|
||||
|
||||
primaryLinePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||
|
@ -189,6 +158,20 @@ class GraphView @JvmOverloads constructor(
|
|||
style = Paint.Style.FILL
|
||||
}
|
||||
|
||||
primaryTextPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||
color = primaryLineColor
|
||||
style = Paint.Style.FILL
|
||||
textSize = labelTextSize
|
||||
textAlign = Paint.Align.RIGHT
|
||||
}
|
||||
|
||||
secondaryTextPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||
color = secondaryLineColor
|
||||
style = Paint.Style.FILL
|
||||
textSize = labelTextSize
|
||||
textAlign = Paint.Align.RIGHT
|
||||
}
|
||||
|
||||
graphPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||
color = graphColor
|
||||
}
|
||||
|
@ -198,6 +181,14 @@ class GraphView @JvmOverloads constructor(
|
|||
strokeWidth = 0f
|
||||
style = Paint.Style.STROKE
|
||||
}
|
||||
|
||||
// Determine how much padding to leave on the right/end of the chart so there's
|
||||
// space for the labels. The widest possible label string is "1000.0M", so
|
||||
// compute that width, with some additional space on the left to separate the
|
||||
// label from the line.
|
||||
val labelBounds = Rect()
|
||||
primaryTextPaint.getTextBounds("1000.0M", 0, 7, labelBounds)
|
||||
paddingEnd = (4 * lineWidth) + labelBounds.width() + labelBounds.left
|
||||
}
|
||||
|
||||
private fun initializeVertices() {
|
||||
|
@ -264,7 +255,7 @@ class GraphView @JvmOverloads constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun dataSpacing(data: List<Any>) = width.toFloat() / max(data.size - 1, 1).toFloat()
|
||||
private fun dataSpacing(data: List<Any>) = (width.toFloat() - paddingEnd) / max(data.size - 1, 1).toFloat()
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
super.onDraw(canvas)
|
||||
|
@ -279,7 +270,7 @@ class GraphView @JvmOverloads constructor(
|
|||
val pointDistance = dataSpacing(primaryLineData)
|
||||
|
||||
// Vertical tick marks
|
||||
for (i in 0 until primaryLineData.size + 1) {
|
||||
for (i in primaryLineData.indices) {
|
||||
drawLine(
|
||||
i * pointDistance,
|
||||
height.toFloat(),
|
||||
|
@ -290,7 +281,7 @@ class GraphView @JvmOverloads constructor(
|
|||
}
|
||||
|
||||
// X-axis
|
||||
drawLine(0f, height.toFloat(), width.toFloat(), height.toFloat(), metaPaint)
|
||||
drawLine(0f, height.toFloat(), width.toFloat() - paddingEnd, height.toFloat(), metaPaint)
|
||||
|
||||
// Data lines
|
||||
drawLine(
|
||||
|
@ -298,36 +289,84 @@ class GraphView @JvmOverloads constructor(
|
|||
linePath = secondaryLinePath,
|
||||
linePaint = secondaryLinePaint,
|
||||
circlePaint = secondaryCirclePaint,
|
||||
lineThickness = lineWidth,
|
||||
)
|
||||
drawLine(
|
||||
canvas = canvas,
|
||||
linePath = primaryLinePath,
|
||||
linePaint = primaryLinePaint,
|
||||
circlePaint = primaryCirclePaint,
|
||||
lineThickness = lineWidth,
|
||||
)
|
||||
|
||||
// Data text
|
||||
drawEndText(
|
||||
canvas,
|
||||
formatNumber(primaryLineData.last(), 1000),
|
||||
formatNumber(secondaryLineData.last(), 1000),
|
||||
primaryLinePath,
|
||||
secondaryLinePath,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun drawLine(
|
||||
canvas: Canvas,
|
||||
linePath: Path,
|
||||
linePaint: Paint,
|
||||
circlePaint: Paint,
|
||||
lineThickness: Float,
|
||||
) {
|
||||
private fun drawLine(canvas: Canvas, linePath: Path, linePaint: Paint, circlePaint: Paint) {
|
||||
canvas.apply {
|
||||
drawPath(
|
||||
linePath,
|
||||
linePaint,
|
||||
)
|
||||
|
||||
val pm = PathMeasure(linePath, false)
|
||||
val coord = floatArrayOf(0f, 0f)
|
||||
pm.getPosTan(pm.length * 1f, coord, null)
|
||||
|
||||
drawCircle(coord[0], coord[1], lineThickness * 2f, circlePaint)
|
||||
drawPath(linePath, linePaint)
|
||||
val (x, y) = pathEnd(linePath)
|
||||
drawCircle(x, y, lineWidth * 2f, circlePaint)
|
||||
}
|
||||
}
|
||||
|
||||
private fun drawEndText(
|
||||
canvas: Canvas,
|
||||
primaryValue: String,
|
||||
secondaryValue: String,
|
||||
primaryLinePath: Path,
|
||||
secondaryLinePath: Path,
|
||||
) {
|
||||
var (primaryX, primaryY) = pathEnd(primaryLinePath)
|
||||
var (_, secondaryY) = pathEnd(secondaryLinePath)
|
||||
|
||||
val primaryBounds = Rect()
|
||||
val secondaryBounds = Rect()
|
||||
primaryTextPaint.getTextBounds(primaryValue, 0, primaryValue.length, primaryBounds)
|
||||
secondaryTextPaint.getTextBounds(secondaryValue, 0, secondaryValue.length, secondaryBounds)
|
||||
|
||||
// Adjust both texts to horizontally align with their respective circle endpoints
|
||||
primaryY += primaryBounds.height().toFloat() / 2
|
||||
secondaryY += secondaryBounds.height().toFloat() / 2
|
||||
|
||||
// Force the two apart if they overlap
|
||||
val overlap = primaryY - (secondaryY - secondaryBounds.height())
|
||||
// First try and force them both apart
|
||||
if (overlap > 0) {
|
||||
secondaryY += (overlap / 2) + 5
|
||||
primaryY -= (overlap / 2) + 5
|
||||
}
|
||||
// Now, if secondary is off the canvas move both of them up to compensate
|
||||
val secondaryClip = secondaryY - canvas.height
|
||||
if (secondaryClip > 0) {
|
||||
secondaryY -= secondaryClip
|
||||
primaryY -= secondaryClip
|
||||
}
|
||||
|
||||
// The number text is right aligned to ensure they line up. The primary text
|
||||
// (total usage) is always going to be larger than the secondary text, so use
|
||||
// that to determine the X position of the right-hand edge of the text. This is:
|
||||
// - primaryX
|
||||
// - + 4 * lineWidth (spacing between the line circle and the text)
|
||||
// - + primaryBounds.width() (width of the text)
|
||||
// - + primaryBounds.left (left margin of the text)
|
||||
val textX = primaryX + (4 * lineWidth) + primaryBounds.width() + primaryBounds.left
|
||||
canvas.apply {
|
||||
drawText(primaryValue, textX, primaryY, primaryTextPaint)
|
||||
drawText(secondaryValue, textX, secondaryY, secondaryTextPaint)
|
||||
}
|
||||
}
|
||||
|
||||
private fun pathEnd(path: Path): Pair<Float, Float> {
|
||||
val pm = PathMeasure(path, false)
|
||||
val coord = floatArrayOf(0f, 0f)
|
||||
pm.getPosTan(pm.length * 1f, coord, null)
|
||||
return Pair(coord[0], coord[1])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,48 +21,10 @@
|
|||
android:importantForAccessibility="no"
|
||||
app:graphColor="?android:colorBackground"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/current_usage"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:lineWidth="2sp"
|
||||
app:metaColor="@color/tusky_blue_light"
|
||||
app:primaryLineColor="@color/tusky_blue"
|
||||
app:proportionalTrending="true"
|
||||
app:secondaryLineColor="@color/tusky_red" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/current_usage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:importantForAccessibility="no"
|
||||
android:paddingStart="6dp"
|
||||
android:textAlignment="textEnd"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textColor="@color/tusky_blue"
|
||||
android:textSize="8sp"
|
||||
android:textStyle="normal"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toTopOf="@id/current_accounts"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/graph"
|
||||
tools:text="12 345" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/current_accounts"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:importantForAccessibility="no"
|
||||
android:paddingStart="6dp"
|
||||
android:textAlignment="textEnd"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textColor="@color/tusky_red"
|
||||
android:textSize="8sp"
|
||||
android:textStyle="normal"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toBottomOf="@id/graph"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/graph"
|
||||
tools:text="12 345" />
|
||||
app:proportionalTrending="true" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/legend_container"
|
||||
|
@ -99,7 +61,7 @@
|
|||
android:importantForAccessibility="no"
|
||||
android:textAlignment="textEnd"
|
||||
android:textAppearance="?android:attr/textAppearanceListItemSmall"
|
||||
android:textColor="@color/tusky_blue"
|
||||
android:textColor="@color/pachli_blue"
|
||||
android:textStyle="normal|bold"
|
||||
app:layout_constrainedWidth="false"
|
||||
app:layout_constraintEnd_toStartOf="@id/barrier2"
|
||||
|
@ -129,7 +91,7 @@
|
|||
android:importantForAccessibility="no"
|
||||
android:textAlignment="textEnd"
|
||||
android:textAppearance="?android:attr/textAppearanceListItemSmall"
|
||||
android:textColor="@color/tusky_red"
|
||||
android:textColor="@color/pachli_orange"
|
||||
android:textStyle="normal|bold"
|
||||
app:layout_constrainedWidth="false"
|
||||
app:layout_constraintEnd_toStartOf="@id/barrier2"
|
||||
|
@ -158,5 +120,4 @@
|
|||
app:constraint_referenced_ids="total_usage,total_accounts"
|
||||
tools:layout_editor_absoluteY="8dp" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
@ -21,48 +21,10 @@
|
|||
android:importantForAccessibility="no"
|
||||
app:graphColor="?android:colorBackground"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/current_usage"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:lineWidth="2sp"
|
||||
app:metaColor="@color/tusky_blue_light"
|
||||
app:primaryLineColor="@color/tusky_blue"
|
||||
app:proportionalTrending="true"
|
||||
app:secondaryLineColor="@color/tusky_red" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/current_usage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:importantForAccessibility="no"
|
||||
android:paddingStart="6dp"
|
||||
android:textAlignment="textEnd"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textColor="@color/tusky_blue"
|
||||
android:textSize="8sp"
|
||||
android:textStyle="normal"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toTopOf="@id/current_accounts"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/graph"
|
||||
tools:text="12 345" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/current_accounts"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:importantForAccessibility="no"
|
||||
android:paddingStart="6dp"
|
||||
android:textAlignment="textEnd"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textColor="@color/tusky_red"
|
||||
android:textSize="8sp"
|
||||
android:textStyle="normal"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toBottomOf="@id/graph"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/graph"
|
||||
tools:text="12 345" />
|
||||
app:proportionalTrending="true" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/legend_container"
|
||||
|
@ -99,7 +61,7 @@
|
|||
android:importantForAccessibility="no"
|
||||
android:textAlignment="textEnd"
|
||||
android:textAppearance="?android:attr/textAppearanceListItemSmall"
|
||||
android:textColor="@color/tusky_blue"
|
||||
android:textColor="@color/pachli_blue"
|
||||
android:textStyle="normal|bold"
|
||||
app:layout_constrainedWidth="false"
|
||||
app:layout_constraintEnd_toStartOf="@id/usageLabel"
|
||||
|
@ -132,7 +94,7 @@
|
|||
android:importantForAccessibility="no"
|
||||
android:textAlignment="textEnd"
|
||||
android:textAppearance="?android:attr/textAppearanceListItemSmall"
|
||||
android:textColor="@color/tusky_red"
|
||||
android:textColor="@color/pachli_orange"
|
||||
android:textStyle="normal|bold"
|
||||
app:layout_constrainedWidth="false"
|
||||
app:layout_constraintEnd_toStartOf="@+id/accountsLabel"
|
||||
|
|
|
@ -13,15 +13,6 @@
|
|||
<attr name="description" format="string|reference" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="GraphView">
|
||||
<attr name="primaryLineColor" format="reference|color" />
|
||||
<attr name="secondaryLineColor" format="reference|color" />
|
||||
<attr name="lineWidth" format="dimension" />
|
||||
<attr name="graphColor" format="reference|color" />
|
||||
<attr name="metaColor" format="reference|color" />
|
||||
<attr name="proportionalTrending" format="boolean" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="SliderPreference">
|
||||
<attr name="android:value" format="string|reference" />
|
||||
<attr name="android:valueFrom" format="string|reference" />
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2024 Pachli Association
|
||||
~
|
||||
~ This file is a part of Pachli.
|
||||
~
|
||||
~ This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
~ GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
~ License, or (at your option) any later version.
|
||||
~
|
||||
~ Pachli is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
~ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
~ Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License along with Pachli; if not,
|
||||
~ see <http://www.gnu.org/licenses>.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<!-- Style to use for GraphView in the theme. -->
|
||||
<attr name="graphViewStyle" format="reference"/>
|
||||
|
||||
<declare-styleable name="GraphView">
|
||||
<attr name="primaryLineColor" format="reference|color" />
|
||||
<attr name="secondaryLineColor" format="reference|color" />
|
||||
<attr name="lineWidth" format="dimension" />
|
||||
<attr name="labelTextSize" format="dimension" />
|
||||
<attr name="graphColor" format="reference|color" />
|
||||
<attr name="metaColor" format="reference|color" />
|
||||
<attr name="proportionalTrending" format="boolean" />
|
||||
</declare-styleable>
|
||||
</resources>
|
|
@ -65,12 +65,16 @@
|
|||
<!-- end of material base colors -->
|
||||
|
||||
<color name="tusky_blue">#2b90d9</color>
|
||||
<color name="tusky_blue_light">#56a7e1</color>
|
||||
<color name="tusky_orange">#ca8f04</color>
|
||||
<color name="tusky_orange_light">#fab207</color>
|
||||
<color name="tusky_green">#19a341</color>
|
||||
<color name="tusky_green_light">#25d069</color>
|
||||
<color name="tusky_red">#DF1553</color>
|
||||
|
||||
<color name="pachli_blue">#006382</color>
|
||||
<color name="pachli_orange">#F37B2F</color>
|
||||
<!-- Commented out for the time being as unused, but kept here as reference -->
|
||||
<!-- <color name="pachli_dark_gray">#30383A</color>-->
|
||||
<!-- <color name="pachli_light_gray">#D4D2C6</color>-->
|
||||
|
||||
<color name="white">#fff</color>
|
||||
<color name="black">#000</color>
|
||||
|
|
|
@ -80,6 +80,8 @@
|
|||
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
<item name="android:windowLightStatusBar">?attr/isLightTheme</item>
|
||||
|
||||
<item name="graphViewStyle">@style/Pachli.Widget.GraphView</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme" parent="Theme.Pachli" />
|
||||
|
@ -159,6 +161,12 @@
|
|||
<item name="android:background">@color/black</item>
|
||||
</style>
|
||||
|
||||
<style name="Pachli.Widget.GraphView" parent="">
|
||||
<item name="primaryLineColor">@color/pachli_blue</item>
|
||||
<item name="secondaryLineColor">@color/pachli_orange</item>
|
||||
<item name="lineWidth">2sp</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Pachli.Black" parent="Base.Theme.Black" />
|
||||
|
||||
<!-- customize the shape of the avatars in account selection list -->
|
||||
|
|
Loading…
Reference in New Issue