How can you import a list of integers in a function while making an extension?

I can put the values ​​one by one and then the block looks like this:
Img2

But how do I make it look like this?
Img3

You need to use YailList parameter.

The code below is an example. You can use code like this inside the function where you have assigned the YailList parameter.

for (final Object o : listItems.toArray()) {
      try {
        // your list code here
      } catch (Exception e) {
        throw new YailRuntimeError(e.toString(), "Exception");
      }
    }
  }
1 Like

I don't understand. Where to put YailList in my list of parameters? Can you provide an example?
I found something here but it is not clear because in my case after YailList exists another parameters.

look in

public void SetGradientBackground(AndroidViewComponent component, Object orientation, int color1, int color2, int color3)

you might want to get rid of the int parameters, replace them with only 1 YailList parameter.

@SimpleFunction(description = "Set gradient background color of component.")
  public void SetGradientBackground(AndroidViewComponent component, YailList listOfColors) {
    View view = component.getView();
    int[] colors = new int[listOfColors.size()];

    for (int i = 0; i < listOfColors.size(); i++) {
      colors[i] = (int) listOfColors.get(i);
    }

    // Do what you want to do with `view` and `colors`.
  }

Does not work. I use Niotron IDE. I comment all the code below function, I keep only the parameters. If I delete YailList the code is compilled with success.

[javac] An annotation processor threw an uncaught exception.
[javac] Consult the following stack trace for details.
[javac] java.lang.IllegalArgumentException: Cannot convert Java type 'YailList' to Yail type

You've to import these classes.

import android.graphics.drawable.GradientDrawable;
import com.google.appinventor.components.runtime.util.YailList;
import com.google.appinventor.components.runtime.HVArrangement;

Now try this code.

@SimpleFunction(description = "Set gradient background color of component.")
  public void SetGradientBackground(HVArrangement component, int orientation, YailList listOfColors) {
    int[] colors = new int[listOfColors.size()];

    for (int i = 0; i < listOfColors.size(); i++) {
      colors[i] = (int) listOfColors.get(i);
    }

    GradientDrawable.Orientation orientationForDrawable = GradientDrawable.Orientation.TOP_BOTTOM;

    switch (orientation) {
      case 1:
        orientationForDrawable = GradientDrawable.Orientation.BL_TR;
        break;
      case 2:
        orientationForDrawable = GradientDrawable.Orientation.BOTTOM_TOP;
        break;
      case 3:
        orientationForDrawable = GradientDrawable.Orientation.BR_TL;
        break;
      case 4:
        orientationForDrawable = GradientDrawable.Orientation.LEFT_RIGHT;
        break;
      case 5:
        orientationForDrawable = GradientDrawable.Orientation.RIGHT_LEFT;
        break;
      case 6:
        orientationForDrawable = GradientDrawable.Orientation.TL_BR;
        break;
      case 7:
        orientationForDrawable = GradientDrawable.Orientation.TOP_BOTTOM;
        break;
      case 8:
        orientationForDrawable = GradientDrawable.Orientation.TR_BL;
        break;
      default:
        break;
    }

    GradientDrawable gradientDrawable = new GradientDrawable(orientationForDrawable, colors);
    component.getView().setBackground(gradientDrawable);
  }
2 Likes

I thought I had to import something. Too bad the IDE doesn't warn about this. Visual Studio does this very well and then you know what to do. I think the answer should have started with the import of the required classes.
Now is working. Thanks.

1 Like

The extension is compiled but when I use it in Inventor it does absolutely nothing.

Back to Niotron IDE....
If I use a try-catch block I get this error:

/compiler/android/src/rZrIr/com/aicode/canvasGradient/CanvasGradient.java:105: error: cannot find symbol
[javac] throw new YailRuntimeError(e.toString(), "Exception");
[javac] ^
[javac] symbol: class YailRuntimeError

You've to import this class.

import com.google.appinventor.components.runtime.errors.YailRuntimeError;

This code does not work.

for (int i = 0; i < listOfColors.size(); i++) 
{
    colors[i] = (int) listOfColors.get(i);
}

But this one works. I think it is about string converting to int.

int [] colors = new int[listOfColors.size()];
    int j = 0;
    for(String e : listOfColors.toStringArray())
    {
    colors[j] = Integer.parseInt(e); 
    j++;
    }
1 Like

Now my code looks like this:

mport com.google.appinventor.components.annotations.DesignerComponent;
import com.google.appinventor.components.annotations.SimpleObject;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.annotations.SimpleEvent;
import com.google.appinventor.components.annotations.SimpleProperty;
import com.google.appinventor.components.common.ComponentCategory;
import com.google.appinventor.components.runtime.AndroidNonvisibleComponent;
import com.google.appinventor.components.runtime.AndroidViewComponent;
import com.google.appinventor.components.runtime.ComponentContainer;
import com.google.appinventor.components.runtime.EventDispatcher;

import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.InsetDrawable;
import android.view.View;

import android.graphics.Rect;
import com.google.appinventor.components.runtime.errors.YailRuntimeError;
import com.google.appinventor.components.runtime.util.YailList;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.TransitionDrawable;
import android.graphics.drawable.shapes.RectShape;
import android.graphics.Canvas;

@DesignerComponent(version = 1,
                    category = ComponentCategory.EXTENSION,
                    description = "",
                    nonVisible = true,
                    iconName = "")

@SimpleObject(external = true)

public class CanvasGradient extends AndroidNonvisibleComponent 
{
    
    public CanvasGradient(ComponentContainer container) 
    {
        super(container.$form());
    }
    
@SimpleFunction(description = "")
 public void SetGradientBackground(
 AndroidViewComponent component, 
 Object orientation,
 int cornerRadius,
 YailList listOfPaddings,
 YailList listOfColors ) 
 {
   try
   {
    View view = component.getView();

    if(listOfPaddings.size() == 1)
    {
        //some code here to handle single item 
        return;
    }

    int [] paddings = new int[listOfPaddings.size()];
    int i = 0;
    for(String e : listOfPaddings.toStringArray())
    {
        paddings[i] = Integer.parseInt(e); 
        i++;
    }

    if(listOfColors.size() == 1)
    {
        //some code here to handle single item
        return;
    }

    int [] colors = new int[listOfColors.size()];
    int j = 0;
    for(String e : listOfColors.toStringArray())
    {
        colors[j] = Integer.parseInt(e); 
        j++;
    }

    GradientDrawable gradient = new GradientDrawable( (GradientDrawable.Orientation) orientation, colors);

    Rect drawablePadding = new Rect();
    gradient.getPadding(drawablePadding);
    gradient.setShape(GradientDrawable.RECTANGLE);
    gradient.setCornerRadius(cornerRadius);
 
    int lp = view.getPaddingLeft() + paddings[0];
    int tp = view.getPaddingTop() + paddings[1];
    int rp = view.getPaddingRight() + paddings[2];
    int bp = view.getPaddingBottom() + paddings[3];

    view.setBackground(gradient);
    view.setPadding(lp, tp, rp, bp);
   }
   catch (Exception e) 
   {
    throw new YailRuntimeError(e.toString(), "Exception");
   }
 } 

    @SimpleEvent(description = "")
    public void ErrorOccured(String error) 
    {
        EventDispatcher.dispatchEvent(this, "ErrorOccured", error);
    }

    @SimpleProperty(description = "")
    public Object TopToBottom() {
        return GradientDrawable.Orientation.TOP_BOTTOM;
    }

    @SimpleProperty(description = "")
    public Object LeftToRight() {
        return GradientDrawable.Orientation.LEFT_RIGHT;
    }

    @SimpleProperty(description = "")
    public Object BottomToTop() {
        return GradientDrawable.Orientation.BOTTOM_TOP;
    }

    @SimpleProperty(description = "")
    public Object RightToLeft() {
        return GradientDrawable.Orientation.RIGHT_LEFT;
    }

    @SimpleProperty(description = "")
    public Object BottomLeftToTopRight() {
        return GradientDrawable.Orientation.BL_TR;
    }

    @SimpleProperty(description = "")
    public Object TopLeftToBottomRight() {
        return GradientDrawable.Orientation.TL_BR;
    }

    @SimpleProperty(description = "")
    public Object TopRightToBottomLeft() {
        return GradientDrawable.Orientation.TR_BL;
    }

    @SimpleProperty(description = "")
    public Object BottomRightToTopLeft() {
        return GradientDrawable.Orientation.BR_TL;
    }

    @SimpleFunction(description = "")
    public int ParseColor(String color) {
        return Color.parseColor(color);
    }
}

But the colors accepted is only 24 bit (RGB). So how to put the alpha channel in order to have 32 bit (RGBA) color?

Search on Google or Stack Overflow.

The code below seems to work from 255 to 128, but if the transparency drops below 128 it switches to transparent black without changing anything.

int j = 0;
    for(String str : bgListOfColors.toStringArray())
    {
        //avoid crash if the color also contains the alpha channel
        //and the max/min value for integer is exceeded
        Long num = Long.valueOf(str);
        int min = Integer.MIN_VALUE;
        int max = Integer.MAX_VALUE;
        Integer n = 0;
        if (num > max) 
        {
            n = max;
        }
        if (num < min) 
        {
            n = min;
        }
        if (num <= max && num >= min)
        {
            n = Integer.valueOf(str);
        }
         
        colors[j] = n;
        j++;
    }
   
    GradientDrawable gradient = new GradientDrawable( (GradientDrawable.Orientation) orientation, colors);

The code that works:

int j = 0;
    for(String str : bgListOfColors.toStringArray())
    {
        Long num = Long.valueOf(str);
        int newColor = num.intValue();
        colors[j] = newColor;
        j++;
    }

What is the purpose of subtracting 2^32 from the color in the blocks? The value returned by the make color block should already be in the range of a Java int so this seems like it would move the value outside of the desired range which means that intValue() might return something unexpected. Specifically, when calling intValue() on a Long, a "narrowing primitive conversion" occurs, which simply lops the higher order bits off without preserving sign, etc. This might explain why your clamping scheme in the first code blocks seems to have odd behavior.

1 Like

You are perfectly right. It is not necessary to subtract 2^32 from the color in the blocks.
My mistake because I didn't understand things correctly.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.