Jetpack compose how to animate multiple values - kotlin

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),
)
}

Related

how to use mpandroidchart to draw a barchart with intervals

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:

Kotlin how to disable a btn depending on condition

I have seen a code that do the following:
button.isEnabled = false
button.isClickable = false
I do not know if this was an older way of doing it. I am just not sure how it will be implemented into my code:
lateinit var dialog:AlertDialog
// Initialize an array of colors
var checked = 0
val items = arrayOf("CHECKED", "UNCHECKED")
val builder = AlertDialog.Builder(context)
builder.setTitle(R.string.dialogTitleDel)
builder.setSingleChoiceItems(items,-1) { _, which ->
checked = which + 1
}
builder.setPositiveButton("Yes"){dialogInterface, which ->
if( checked > 0){
modal.tvdone = 1
Log.e("Clicked", "Successful delivery")
notifyDataSetChanged()
}
// else{PositiveButton.setEnabled(false)}
}
dialog = builder.create()
dialog.setCancelable(false)
dialog.show()
What will be the correct way of disabling the positive button, until a condition is met?
It's not clear what you are trying to achieve
as per your commented line your are trying to disable the positive button on positive button click
Regardless, you need to get the dialog's positive button and then enable/disable it
dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = false

Fixing Some Kotlin Syntax

I just finish built a simple android music app with Java, then I convert the java files to Kotlin with Kotlin plugin for Android Studio.
There are some error, in MainActivity.kt
private fun display() {
val mySongs = findSong(Environment.getExternalStorageDirectory())
items = arrayOf(mySongs.size.toString())
for (i in mySongs.indices) {
items[i] = mySongs[i].name.toString().replace(".mp3", "").replace(".wav", "")
}
val adp = ArrayAdapter(this, android.R.layout.simple_list_item_1, items!!)
listView!!.adapter = adp
listView!!.onItemClickListener = AdapterView.OnItemClickListener { adapterView, view, position, l -> startActivity(Intent(applicationContext, PlayerActivity::class.java).putExtra("pos", position).putExtra("songs", mySongs)) }
}
this line : items[i] = mySongs[i].name.toString().replace(".mp3","").replace(".wav", "")
showing an error: Smart cast to 'Array' is a mutable property that could have been changed by this time.
and on the PlayerActivity.kt
val i = intent
val b = i.extras
mySongs = b.getParcelableArrayList<Parcelable>(mySongs.toString())
position = b.getInt("pos", 0)
val u = Uri.parse(mySongs!![position].toString())
mediaPlayer = MediaPlayer.create(applicationContext, u)
the b.getParcelableArrayList<Parcelable>(mySongs.toString()) has a problem says Type mismatch.
Anyone can help me fix this? Thank You
This line
items = arrayOf(mySongs.size.toString())
creates an array of 1 element containing a string with the size of my songs. ex: ["23"]
You could use this instead: arrayOfNulls(mySongs.size)
For the other question:
mySongs = b.getParcelableArrayList<Parcelable>(mySongs.toString())
should return the same type as (I assume that it was the same code than in main activity because they are in 2 differents files and the context of mySongs is not provided)
val mySongs = findSong(Environment.getExternalStorageDirectory())
mySongs will have be the same type as the result of findSong.
Also you should use var instead of val because val are immutable

CreateJS Tick function not updating from external values.

I think this might be quite basic, I'm still learning CreateJS. I won't include all the code as its a large program but basically.
Outside of my tick function I have this code:
var hitOrMiss = 'Mada';
function hit()
{
hitOrMiss = 'Hit';
//alert(hitOrMiss);
}
function miss()
{
hitOrMiss = 'Miss';
//alert(hitOrMiss);
}
When I click a button and call these they are testing ok (alerting out the values).
Inside my tick() function the values are not being picked up.
if(hitOrMiss = 'Mada')
{
var basic = 'basic';
}
else if(hitOrMiss = 'Hit')
{
if(gamePrincessBmpAnimation.x < 1000)
{
gamePrincessBmpAnimation.x += gamePrincessBmpAnimation.vX;
var basic = 'Not basic';
}
}
else if(hitOrMiss = 'Miss')
{
if(gamePrincessBmpAnimation.x > 60)
{
gamePrincessBmpAnimation.x -+ gamePrincessBmpAnimation.vX;
var basic = 'Miss Not basic';
}
}
Do I need to specify a listener, if so how should it be set up?
I have already triggered the below, Does something similar need to be added to the tick function?
createjs.Ticker.addListener(window);
createjs.Ticker.useRAF = true;
createjs.Ticker.setFPS(60);
gameStage.update();
The other if statements within the tick function are all firing, an example of which:
if (bmpAnimation.x >= screen_width - 16) {
// We've reached right side of our screen
// We need to walk left to go back to our initial position
bmpAnimation.direction = -90;
}
Any help would be appreciated! :)
Fixed this one, wasn't a createJS issue, was a silly Javascript issue, the code here: else if(hitOrMiss = 'Hit') should have been else if(hitOrMiss == 'Hit') etc.

Adobe Edge Animate—how do I get the current label?

In Adobe Edge Animate, how do I get the name of the label that corresponds to a given time? I've seen that I can get the current time as an integer using
sym.getPosition()
but if there's a label at that position, how do I get the label as a string?
function getLabel() {
var stage = sym.getComposition().getStage();
var labels = stage.timelines['Default Timeline'].labels;
var currentLabel;
var currentPosition = stage.getPosition();
$.each( labels, function( label, position ){
if (position <= currentPosition) currentLabel = label;
});
return currentLabel;
}
console.log( getLabel() );
this will return the label on (or next previous to) the current position.
For those of us here looking for a Adobe Animate 2019 solution (like I was), it's similar, but slightly different:
function getLabel(_this) {
var currentLabel;
var currentPosition = _this.currentFrame;
_this.labels.forEach(function( label, index ){
if (label.position <= currentPosition) currentLabel = label.label;
});
return currentLabel;
}
Your position on the timeline is easier to get, and the labels object is organized differently. (Also jQuery is unavailable.)