how can i make user to choose(by clicking on image) between 2 images n times using for loop?
below, i have created an array of 4 drawable images and set it to rank2.
on each loop, user will choose one between 2 images, then selected image is saved in rank1 array.
because there are only 4 drawables right now, it will only loop 2 times.
val imageView1 = findViewById<ImageView>(R.id.imageView1);
val imageView2 = findViewById<ImageView>(R.id.imageView2);
val textView = findViewById<TextView>(R.id.textView);
var rank2 = mutableListOf(R.drawable.img1,R.drawable.img2,R.drawable.img3,R.drawable.img4)
val rank1: MutableList<Int> = ArrayList()
var x = 0;
while(x<2) {//run it 2 times
var temp = arrayOf(rank2[x*2], rank2[(x*2)+1]);
imageView1.setImageResource(temp[0]);
imageView2.setImageResource(temp[1]);
imageView1.setOnClickListener{
rank1.add(temp[0]);
x++;
}
imageView1.setOnClickListener{
rank1.add(temp[1]);
x++;
}
}
but, this one falls into infinite loop.
how can i fix this?
No need to use while loop. A counting variable is all you need.
var rank2 = mutableListOf(R.drawable.img1,R.drawable.img2,R.drawable.img3,R.drawable.img4)
val rank1: MutableList<Int> = ArrayList()
imageView1.setImageResource(rank2[0]);
imageView2.setImageResource(rank2[1]);
var x = 0
imageView1.setOnClickListener{
if (x < 2) {
rank1.add(rank2[2 * x])
imageView1.setImageResource(rank2[2 * (x + 1)])
imageView2.setImageResource(rank2[2 * (x + 1) + 1])
x++
}
}
imageView2.setOnClickListener{
if (x < 2) {
rank1.add(rank2[2 * x + 1])
imageView1.setImageResource(rank2[2 * (x + 1)])
imageView2.setImageResource(rank2[2 * (x + 1) + 1])
x++
}
}
Try to create a recursive method instead of a cycle that calls itself nLoops times. Try something like this:
fun c(b: Int, nLoops: Int) {
if (b!=nLoops) {
var x = b;
var temp = arrayOf(rank2[x * 2], rank2[(x * 2) + 1]);
imageView1.setImageResource(temp[0]);
imageView2.setImageResource(temp[1]);
imageView1.setOnClickListener
{
rank1.add(temp[0]);
x++;
c(x, nLoops);
}
imageView1.setOnClickListener
{
rank1.add(temp[1]);
x++;
c(x, nLoops);
}
}
}
When you run somethink like this with b=0 and nLoops = 2 it will execute your code only ehwn you press the image for 2 times.
Related
I need to create an ArrayList<Float>() where each next element of list must be bigger from previous by a certain number. the last element of array always = 100f but the size can change. For example, if size = 5,
I need something like this ArrayList<Float> list = arrayOf(20f, 40f,60f,80f,100f). But the problem is that I don't know how many elements I will have and need to do everything dynamically.
Here is my list
var size= 5
var progress= 100/size.toFloat()
list = ArrayList<Float>()
for (i in 0 until size) {
list.add(progress)
}
and here I am trying to add next and previous elements
for (i in 0 until list.size) {
val curr = list[i]
val next = list[(i + prog).toInt()]
}
But don't know how to add it to ArrayList
Please, help!
I assume that the values are distributed evenly.
In this case, this is simple mathmatics:
Array[index] = index * step = index * (100 / size)
val max = 100
val size = 7
val step = max / size.toFloat()
val list = ArrayList<Float>(size)
for (i in 0 until size) {
list.add(step * (i+1))
}
// or better with kotlin collections
val klist = List(size) { index -> step * (index + 1) }
I have problem with my algoritm. I delete position on 0, but my dataset ddint move like -1. Then i add a new Entry on position 25. Continuous this maked my project alway delete last entry and non stop adding the Entry in position 25.
Here is code:
private void addEntry() {
data = mChart.getData();
if (set1 == null) {
set1 = createSet();
data.addDataSet(set1);
}
int prog = 1;
for (int i = 0; i < prog; i++) {
float val = (float) (Math.random() * 2);
float high = (float) (Math.random() * 1) + 2f;
float low = (float) (Math.random() * 1) + 2f;
float open = (float) (Math.random() * 2) + 1f;
float close = (float) (Math.random() * 2) + 1f;
boolean even = i % 2 == 0;
data.addEntry(new CandleEntry(25, val + high, val - low, even ? val + open : val - open,
even ? val - close : val + close), 0);
data.notifyDataChanged();
mChart.notifyDataSetChanged();
mChart.setVisibleXRangeMaximum(25);
mChart.moveViewTo(data.getEntryCount() - 24, 2f, YAxis.AxisDependency.RIGHT);
}
}
private void removeLastEntry() {
CandleData data = mChart.getData();
if (data != null) {
ICandleDataSet set = data.getDataSetByIndex(0);
if (set != null) {
Entry e = set.getEntryForIndex(0);
data.removeEntry(e, 0);
data.notifyDataChanged();
mChart.notifyDataSetChanged();
mChart.invalidate();
}
}
}
DataSet#getEntryForIndex(int index) returns the entry that is first in the backing array of Entry which may or may not be the Entry with the minimum x value on the chart. From the javadoc:
Returns the Entry object found at the given index (NOT xIndex) in the values array.
I suspect you actually want to use something like the following:
float xMin = dataSet.getXMin();
dataSet.remove(dataSet.getEntryForXPos(xMin);
See the javadoc here.
However, your use case is a little bit unusual. You want all the other entries to "move down", it would seem, when you remove the Entry with the minimum value. If you are only doing this infrequently, it may be easier to construct a new dataset when you do that. Please note that while adding Entry to the chart is easy, random access to Entry and removing them is not supported so well. See the following note in the wiki
Please be aware that this library does not officially support drawing LineChart data from an Entry list not sorted by the x-position of the entries in ascending manner. Adding entries in an unsorted way may result in correct drawing, but may also lead to unexpected behaviour.
Good night.
I have a for loop to calculate some values along the week, during some weeks. My code compare day of the week with the quantity of days that have passed.
The for only works fine on monday when workday is the same than totdays. The rest of days totact is 0 and the fianl equation become NaN.
int totdias = PrefProteos.getInt("dia",0);
int totact = 0;
float califtot = 0;
int stateday = 0;
float promdias;
float promcalif;
int workdays;
Date day = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("EE", Locale.US);
String dayweek = formatter.format(day);
if (dayweek.equals("Mon")) {
stateday = 1;
}
else if (dayweek.equals("Tue")) {
stateday = 2;
}
else if (dayweek.equals("Wed")) {
stateday = 3;
}
else if (dayweek.equals("Thu")) {
stateday = 4;
}
else if (dayweek.equals("Fri")) {
stateday = 5;
}
else if (dayweek.equals("Sat")) {
stateday = 6;
}
else if (dayweek.equals("Sun")) {
stateday = 7;
}
if (stateday >= totdias) {
workdays = 1;
promdias = totdias;
} else {
workdays = (totdias - (stateday - 1));
promdias = stateday;
}
for (int y = workdays; y == totdias;y++) {
for (int x = 1; x <= 12; x++) {
String activ=PrefProteos.getString("act" + x + "-habit", "");
if (!activ.equals("")) {
float notactiv = PrefProteos.getFloat("act" + x + "-puntdia"+y, 0);
califtot = califtot+notactiv;
totact = totact+1;
}
}
}
promcalif = califtot / (totact * promdias);
You have write your first loop condition wrong, you ask only for to run only if workdays = totdias. I guess you want to loop for each days from workdays to totdias
So correct this block :
for (int y = workdays; y == totdias;y++) {
Into
for (int y = workdays; y <= totdias;y++) {
PS :
Your current loop is like writing
if(workdays == totdias) {
You should provide some more code because we can't understand your PrefProteos class and probably the error is in there.
You should also add the full logcat
And you should tell us which line throws the error.
Anyway there are some errors:
Here
for (int y = workdays;y==totdias;y++){
There is no sense of using an equals condition in a for loop exit condition if both equals condition and looping variable are the same, because it will result in an if loop. This is because the for will work only if workdays == totdias since the beginning, elseway it will not work.
For conditions are:
for(counter = defaultvalue; condition that if true, makes the loop goes on; what to do each loop end)
This means that your code will do:
is y(workdays) == totdias?
if yes, do the loop
add one to y(workdays)
exit because the condition is no more true
if not, don't run the loop
So you simply have to call:
if(y == totdias){
//do code
y++;
}
But probably this is an error, because except for monday, this code will never run! so in others days promdias is not istantiated
In the loop
for (int x = 1; x<=12; x++){
String activ=PrefProteos.getString("act" + x + "-habit", "");
if (!activ.equals("")){
//there must be an error here somewhere
float notactiv=PrefProteos.getFloat("act" + x + "-puntdia"+y, 0);
califtot=califtot+notactiv;
totact=totact+1;
}
}
And this must be throwing an error.
promcalif = califtot/(totact*promdias);
Two options:
promidias or totact are 0. you can't do number/0
As said above, promdias might not be istantiated in other days of the week, because the for loop never run
Btw, float name = 0; is not perfect, change them to float name = 0f;
in Android I would like to draw a PieChart with a dynamically number of pies. Each pie should have a different color from a gradient.
For example I would like to have a gradient from light brown to dark brown. If I need to draw five pies, I need five volors from the start to the end of this gradient.
How can I do that in Java with the Android framework?
I found out that I can create a LinearGradient for a line, i.e.:
LinearGradient lg = new LinearGradient(1, 1, 5, 5, toRGB("lightbrown"), toRGB("darkbrown"), TileMode.REPEAT);
But I did not found any function to get a color from this line, i.e.:
// for the five needed RGB colors from the gradient line
lg.getRGBColor(1, 1);
lg.getRGBColor(2, 2);
lg.getRGBColor(3, 3);
lg.getRGBColor(4, 4);
lg.getRGBColor(5, 5);
Do you have any ideas how I can get this?
Thanks!
You cannot get these values directly from the LinearGradient. The gradient doesn't contain the actual drawing. To get these values, you can paint them to a canvas and pull the colors out of the canvas, or what I'd suggest would be to calculate the values yourself.
It's a repeating linear gradient in five steps and you have the RGB values for the first and last color. The rest is just math. Here's the pseudo code:
int r1 = startColor.red;
int g1 = startColor.green;
int b1 = startColor.blue;
int r2 = endColor.red;
int g2 = endColor.green;
int b2 = endColor.blue;
int redStep = r2 - r1 / 4;
int greenStep = g2 - g1 / 4;
int blueStep = b2 - b1 / 4;
firstColor = new Color(r1, g1, b1);
secondColor = new Color(r1 + redStep, g1 + greenStep, b1 + blueStep);
thirdColor = new Color(r1 + redStep * 2, g1 + greenStep * 2, b1 + blueStep * 2);
fourthColor = new Color(r1 + redStep * 3, g1 + greenStep * 3, b1 + blueStep * 3);
fifthColor = new Color(r1 + redStep * 4, g1 + greenStep * 4, b1 + blueStep * 4);
Another approach that is a little more reusable (I seem to bump into this problem all the time). It's a bit more code. Here is the usage:
int[] colors = {toRGB("lightbrown"), toRGB("darkbrown")};//assuming toRGB : String -> Int
float[] positions = {1, 5};
getColorFromGradient( colors, positions, 1 )
//...
getColorFromGradient( colors, positions, 5 )
Supporting functions
public static int getColorFromGradient(int[] colors, float[] positions, float v ){
if( colors.length == 0 || colors.length != positions.length ){
throw new IllegalArgumentException();
}
if( colors.length == 1 ){
return colors[0];
}
if( v <= positions[0]) {
return colors[0];
}
if( v >= positions[positions.length-1]) {
return colors[positions.length-1];
}
for( int i = 1; i < positions.length; ++i ){
if( v <= positions[i] ){
float t = (v - positions[i-1]) / (positions[i] - positions[i-1]);
return lerpColor(colors[i-1], colors[i], t);
}
}
//should never make it here
throw new RuntimeException();
}
public static int lerpColor( int colorA, int colorB, float t){
int alpha = (int)Math.floor(Color.alpha(colorA) * ( 1 - t ) + Color.alpha(colorB) * t);
int red = (int)Math.floor(Color.red(colorA) * ( 1 - t ) + Color.red(colorB) * t);
int green = (int)Math.floor(Color.green(colorA) * ( 1 - t ) + Color.green(colorB) * t);
int blue = (int)Math.floor(Color.blue(colorA) * ( 1 - t ) + Color.blue(colorB) * t);
return Color.argb(alpha, red, green, blue);
}
I have wrote the util class for calculate colors gradient.
via very, very simple Kotlin code:
val pink = Colar(245, 9, 253)
val lime = Colar(0, 253, 32)
lp_1.colors = (pink toColor lime).run {
gradient { 0 upTo 3 }
}
lp_2.colors = (pink toColor lime).run {
gradient { 0 upTo 9 }
}
lp_3.colors = (pink toColor lime).run {
gradient { 3 upTo 9}
}
Supporting util class
class StepGradientUtil(private var colar1: Colar?, private var colar2: Colar?) {
private var mSteps: Int = 0
infix fun StepGradientUtil.gradient(f: () -> IntRange): IntArray {
val result = f.invoke().map {
it.colorStep()
}.toIntArray()
recycler()
return result
}
infix fun Int.upTo(steps: Int): IntRange {
mSteps = steps
return (this until steps)
}
private fun recycler() {
mSteps = 0
colar1 = null
colar2 = null
}
private fun Int.colorStep() = Color.rgb(
(colar1!!.r * (mSteps - this) + colar2!!.r * this) / mSteps,
(colar1!!.g * (mSteps - this) + colar2!!.g * this) / mSteps,
(colar1!!.b * (mSteps - this) + colar2!!.b * this) / mSteps
)
}
data class Colar(
val r: Int,
val g: Int,
val b: Int
)
infix fun Colar.toColor(colar: Colar) = StepGradientUtil(colar1 = this, colar2 = colar)
See full source code sample on repo
i want to build a component that will be able to show a integer number max 5 digits in the style of the old analog car counters and animate the digit change.
that looks something like this maybe...
i have tried searching for this kinda of examples but i couldn't find anything so far.
in your opinion what is the best approach to achieve this?
i looked at the iphone alarm time picker and as far as i can tell there is only a fixed background and they push the numbers in or out the view. but how do i place the digits in this case and reference them to a particular value?
tnx.
You can try to create your own view, extending view and overriding onDraw().
Here you can use rows of numbers in bitmaps and editing their position based on the number you wish to show.
Dont forget to call invalidate() after setting new numbers to redraw the view.
I will paste an example containing a start for your project.
The bitmap number is a vertical image with numbers from 1-9 (and 0&.)
Ex.
class TickerView extends View { ..
public void setDouble(double d) {
value = d;
invalidate();
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int startx = 0;
int starty = 0;
DecimalFormat df = new DecimalFormat("#0.00");
String str = df.format(value);
String original = Double.toString(value);
Bitmap nums = BitmapFactory.decodeResource(context.getResources(),
R.drawable.numbers);
for (int i = 0; i < str.length(); i++) {
int num = 0;
try {
num = Integer.parseInt(str.charAt(i) + "");
} catch (Exception e) {
num = 10;
}
int numbefore = 0;
try {
numbefore = Integer.parseInt(original.charAt(i -1) + "");
} catch (Exception e) {
numbefore = 0;
}
canvas.drawBitmap(nums, startx + (i * 40), (starty + 40)
- (num * 50) + (numbefore), paintY);
}
paintY.setStrokeWidth(10);
canvas.drawLine(startx, starty+36, startx + (str.length() * 40), starty+36,
paintY);
canvas.drawLine(startx, starty + 90, startx + (str.length() * 40),
starty + 90, paintY);
invalidate();
}
}