The y-axis of the official case starts from 0
I hope to realize the image function through mpandroidchart
You can accomplish this using a stacked bar chart and setting the color of the bottom bar to transparent.
For example:
// Make some fake data - the first array will be the offset,
// with a transparent color. The second is the height of the bar
val offset = listOf(42f, 55f, 55f, 80f, 55f, 110f)
val amount = listOf(50f, 50f, 50f, 50f, 50f, 55f)
val entries = offset.zip(amount).mapIndexed { i, oa ->
BarEntry(i.toFloat(), listOf(oa.first, oa.second).toFloatArray())
}
// To make the bars different colors, make multiple BarDataSets
// instead of just one
val barDataSet = BarDataSet(entries,"data")
barDataSet.colors = listOf(Color.TRANSPARENT, Color.CYAN)
barDataSet.setDrawValues(false)
barChart.setTouchEnabled(false)
barChart.description.isEnabled = false
barChart.legend.isEnabled = false
val yAxis = barChart.axisLeft
yAxis.isEnabled = true
yAxis.axisMinimum = 40f
yAxis.axisMaximum = 160f
yAxis.granularity = 20f
yAxis.textSize = 24f
yAxis.setLabelCount(6, true)
yAxis.setDrawAxisLine(false)
yAxis.gridLineWidth = 1f
yAxis.setDrawGridLines(true)
barChart.axisRight.isEnabled = false
barChart.xAxis.isEnabled = false
barChart.data = BarData(barDataSet)
The result:
Related
I have couple of Path elements in my Canvas and would like to do some complex animations with every one of the Path lines. I am not sure how to approach this. Let's take a look at a simple path.
val line1Path = Path()
line1Path.moveTo(maxTopLeftX, 0f) // top left
line1Path.lineTo(maxBottomLeftX, size.height) // bottom left
line1Path.lineTo(maxBottomLeftX+lineWidth, size.height) // bottom right
line1Path.lineTo(maxTopLeftX+lineWidth, 0f) // top right
Currently I am using updateTransition with animateFloat but this way if I have to make animations for every one of the points only for this Path I would have to have 8 variables just for this 1 object.
Also I would like to do more than just a single value to value animation so something like animateFloatAsState where there are keyframes and I can order my animations seems better for the job, but the issue again is I have to create 8 variables that hold every one of the line positions to just animate this object.
What will be the best way to approach this?
I have been having same issue for days. In my case I use a data class for input data, so I just added an Animatable variable with default initialization to my data class. Then launch it from coroutine scope forEaching every item.
Not sure if this is the correct way to approach such issue, but hope it helps!
Here you have an example of multiple values animated at the same time. A transition is used to orchestrate the value animations.
val interactionSource = remember { MutableInteractionSource() }
val isPressed by interactionSource.collectIsPressedAsState()
val transition = updateTransition(targetState = isPressed, label = "")
val angle by transition.animateFloat(transitionSpec = {
tween(durationMillis = 180, easing = FastOutSlowInEasing)
}, label = ""){
when(it){
true -> 90f
false -> 0f
}
}
val x by transition.animateDp(transitionSpec = {
tween(durationMillis = 180, easing = FastOutSlowInEasing)
}, label = ""){
when(it){
true -> 85.dp
false -> 0.dp
}
}
Column(modifier = Modifier.fillMaxSize().background(Color(0xFFF0F8FF))
.padding(80.dp).wrapContentSize(align = Alignment.BottomCenter),
verticalArrangement = Arrangement.spacedBy(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
// THIS IS THE ANIMATED BOX
Box(Modifier.rotate(angle).offset(x = x)
.background(Color.Red)
.width(20.dp)
.height(150.dp)
)
Box(modifier = Modifier.clickable(interactionSource = interactionSource, indication = null) {}
.hoverable(interactionSource)
.focusable(interactionSource = interactionSource)
.size(100.dp).background(Color.Blue),
)
}
I want to get rid of that space in the legend between the name and the percentage. In the pic, I have highlighted the space in yellow.
For example, I want the first legend item to be "Lithuania (30.5%)". That extra space between "Lithuania" and "30.5%" spoils my UI.
My code for the legend is the following:
// Add and configure Series
var pieSeries = chart.series.push(new am4charts.PieSeries());
pieSeries.dataFields.value = "litres";
pieSeries.dataFields.category = "country";
pieSeries.slices.template.stroke = am4core.color("#fff");
pieSeries.slices.template.strokeWidth = 2;
pieSeries.slices.template.strokeOpacity = 1;
pieSeries.ticks.template.disabled = true;
pieSeries.labels.template.disabled = true;
// This creates initial animation
pieSeries.hiddenState.properties.opacity = 1;
pieSeries.hiddenState.properties.endAngle = -90;
pieSeries.hiddenState.properties.startAngle = -90;
pieSeries.legendSettings.labelText = '{category}';
pieSeries.legendSettings.valueText = null;
pieSeries.labels.template.text = "{category}: {value}";
pieSeries.slices.template.tooltipText = "{category}: {value}";
chart.legend = new am4charts.Legend();
chart.legend.fontSize = 5;
chart.legend.markers.template.width = 5;
chart.legend.markers.template.height = 5;
What change must I make in order to get this done?
You can move the value to the "labelText":
pieSeries.legendSettings.labelText = "{category}: {value.percent.formatNumber('#.0')}%";
And disable value labels altogether:
chart.legend.valueLabels.template.disabled = true;
I am using odoo 10. When I go to tree view then charts then click on pie chart icon. Pie Labels are overlapping at some points. I tried to some work around in /web/static/nvd3/nv.d3.js file but it is either giving me errors or n effect. Could anyone help me how to achieve this without text overlapping on piechart?
/*
Overlapping pie labels are not good. What this attempts to do is, prevent overlapping.
Each label location is hashed, and if a hash collision occurs, we assume an overlap.
Adjust the label's y-position to remove the overlap.
*/
var center = labelsArc[i].centroid(d);
var percent = getSlicePercentage(d);
if (d.value && percent >= labelThreshold) {
var hashKey = createHashKey(center);
if (labelLocationHash[hashKey]) {
center[1] -= avgHeight;
}
labelLocationHash[createHashKey(center)] = true;
}
return 'translate(' + center + ').rotateLabels(-45)'
}
Above code giving me all text labels centered in piechart middle/centre overlapped on each other. if I remove .rotateLabels(-45) then labels are outside the pie circle but some text overlapping on each other. Thanks in advance!
This worked for me. Do not apply rotateLabels(-45) as I have applied in the question. set ShowLabels=true and labelSunbeamLayout=true as shown below in nv.d3.js file.
//============================================================
// Public Variables with Default Settings
//------------------------------------------------------------
var margin = {top: 0, right: 0, bottom: 0, left: 0}
, width = 500
, height = 500
, getX = function(d) { return d.x }
, getY = function(d) { return d.y }
, id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
, container = null
, color = nv.utils.defaultColor()
, valueFormat = d3.format(',.2f')
, showLabels = true
, labelsOutside = true
, labelType = "key"
, labelThreshold = .02 //if slice percentage is under this, don't show label
, donut = false
, title = false
, growOnHover = true
, titleOffset = 0
, labelSunbeamLayout = true
, startAngle = false
, padAngle = false
, endAngle = false
, cornerRadius = 0
, donutRatio = 0.5
, arcsRadius = []
, dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd')
;
I have a stacked column report and i need to show the label value inside each of the series, is this possible. here is the code i have so far. It does look like barcharts have this option, not sure if i need to convert report to that type.
chart.Title.Text = "Total Pipeline - Initiative Count by Release";
chart.Title.Font.Size = 8;
chart.SetPosition(45, 0, 3, 0);
chart.SetSize(400, 300);
chart.Legend.Add();
chart.YAxis.MajorUnit = 10;
var series1 = chart.Series.Add(Chartsheet.Cells["L23:Q23"], Chartsheet.Cells["L22:Q22"]);
series1.HeaderAddress = new ExcelAddress("'Graphs'!K23");
var series2 = chart.Series.Add(Chartsheet.Cells["L24:Q24"], Chartsheet.Cells["L22:Q22"]);
series2.HeaderAddress = new ExcelAddress("'Graphs'!K24");
chart.Legend.Position = eLegendPosition.Bottom;
chart.YAxis.LabelPosition = eTickLabelPosition.NextTo;
chart.XAxis.MajorTickMark = eAxisTickMark.Out;
chart.XAxis.MinorTickMark = eAxisTickMark.None;
chart.ShowDataLabelsOverMaximum = true;
so i just forced a format of a barchart and i have the label option
var chart = (OfficeOpenXml.Drawing.Chart.ExcelBarChart) Chartsheet.Drawings.AddChart("chart", eChartType.ColumnStacked);
I've found a similair question to my problem and so far its working for me, Im getting the row ID printed with a print statement.
I am displaying data from my Database in a tableView. With the onTouch function I want the data showed in a new Scene in a scrollView that gets that data specifically to that clicked row. So for example I am clikcing on the tableView on Capital_NL, it has to show Amsterdam in the scrollView (Scene 2).
This is my code so far:
Scene 1:
local count = 0
local baslikRow = {}
for row in db:nrows("SELECT dua_id, baslik FROM dua") do
count = count + 1
baslikRow[count] = {}
baslikRow[count].baslik = row.baslik
baslikRow[count].dua_id = row.dua_id
end
local function tableViewListener( event )
print(event.phase)
end
local function onRowRender( event )
local row = event.row
local rowHeight = row.contentHeight
local rowWidth = row.contentWidth
local options =
{
parent = row,
text = baslikRow[row.index].baslik,
x = 20,
y = 0,
font = native.systemFont,
fontSize = 16
}
local rowTitle = display.newText(options)
rowTitle:setFillColor( 0, 0, 0 )
rowTitle.anchorX = 0
rowTitle.x = 15
rowTitle.y = rowHeight * 0.5
end
local function onRowTouch( event )
local row = event.row
if event.phase == 'tap' then
print("Pressed rowNR: " .. row.index )
print("Pressed rowID: " .. event.target.params.paramID)
composer.gotoScene("scene2")
end
end
local tableView = widget.newTableView{
left = 0,
top = 0,
height = display.contentHeight,
width = display.contentWidth,
onRowRender = onRowRender,
onRowTouch = onRowTouch,
}
for i = 1, count do
tableView:insertRow
{
rowHeight = 50,
rowid = baslikRow[count].dua_id,
params = { paramID = baslikRow[i].dua_id }
}
end
sceneGroup:insert(tableView)
Scene 2:
---------------------
-- CREATE SCROLLVIEW
---------------------
local scrollView = widget.newScrollView
{
left = 0,
top = 0,
width = display.contentWidth,
height = display.contentHeight,
topPadding = 0,
bottomPadding = 0,
horiontalScrollDisabled = true,
verticalScrollDisable = false,
listener = scrollListener,
}
sceneGroup:insert(scrollView)
---------------------
-- GET DATA FROM DB
---------------------
for row in db:nrows("SELECT metni FROM dua") do
local rowParams =
{
duaID = row.dua_id,
Metni = row.metni,
}
local options =
{
text = row.metni,
x = display.contentCenterX + 20,
y = display.contentHeight / 2,
width = 300,
width = display.contentWidth,
font = native.systemFontBold,
fontSize = 18,
}
local t = display.newText(options)
t:setTextColor(0)
scrollView:insert(t)
end
What I have right now is, whenever I click on, for example Capital_NL or Capital_USA or Capital_Germany, I always get the result Amsterdam back.
How do I pass the data thats in the same Row in the database from Scene 1 to Scene 2
I think you want to display the (metni) data based on the row number tapped on the previuos scene ..
Try this inside scene1 ..
for row in db:nrows("SELECT dua_id, baslik, metni FROM dua") do
count = count + 1
baslikRow[count] = {}
baslikRow[count].baslik = row.baslik
baslikRow[count].dua_id = row.dua_id
baslikRow[count].metni = row.metni
inside the onRowTouch event handler:
composer.gotoScene("scene2",{params = baslikRow[row.index].metni})
This way you can pass the data you want to use .. I guess you don't need to use the database code inside scene2 ..
to access the data passed from scene1 to scene2
local selectedRow = event.params
Then ..
local options =
{
text = selectedRow,
x = display.contentCenterX + 20,
y = display.contentHeight / 2,
width = 300,
width = display.contentWidth,
font = native.systemFontBold,
fontSize = 50,
}
local t = display.newText(options)
t:setTextColor(0)
scrollView:insert(t)
I think thats what you asked for .. If NOT, please explain more and give us a screenshot of your "dua" table ..