On-screen buttons without APWidgets?

edited December 2015 in Android Mode

Hopefully a quick question - As APWidgets is no longer compatible with Processing, any simple way to create an on-screen "save/export" button for Android Mode? There are a few threads about creating buttons, but I cannot use mousePressed on Android, and would prefer not to use the keyboard from, for example, the Ketai library.

Answers

  • @pdf197=== use the android button class + onClickListener() with your save/export method; as for mousePressed use motionEventClass.

  • edited December 2015

    Thanks for the tip @akenaton - so something like...? Except this doesn't work.

    void setup() 
    {
      size(200, 200);
    }
    
    void draw() 
    {
      background(204);
      line(0, 0, mouseX, height);
      line(width, 0, 0, mouseY);
    }    
    
    Button myButton = new Button(this);
        myButton.setText("Save");
        myButton.setOnListener(new.OnClickListener(){
    
        void onClick(){
    
        save("screenshot.tif");
        }
    
  • edited December 2015 Answer ✓

    @PDF197=== yes, "something like this" BUT not really this!

    a) import the android button class;

    b) Button myButton; (declare the Button instance)

        ///setup()--------------
    
        myButton = new Button (this.getActivity()); //you are in a fragment now!!!!!
        myButton.set (text, background color....)
    
        c)  OnClickListener oclMonBouton = new OnClickListener() {
    
            public void onClick(View v) {
    
              println("clicked!!!!");
              //here your save method
            }
          };
    
          myButton.setOnClickListener(oclMonBouton);
    
        d) add the button to your view (and do this in a runnable as you are in a fragment)
    
         getActivity().runOnUiThread(new Runnable() {------------
    
  • That's WAY too deep into Android for me, but thank you @akenaton I am always impressed by your knowledge, and speed of reply. I do need to become more familiar with Android in addition to Processing... I will add it to my list for 2016!!

  • edited December 2015 Answer ✓

    @PDF197===

    (you are right== learn android!!! + Android studio or eclipse) ; as i repeat processing3XX android, till now, is no more than a graphics library for android.

    ---- but try this code:::: (i can implement the motionEvent, but my goal is only to show you how to add a button== so, some imports does not matter here); not tested but it must work (i hope!!!!)

                        import android.content.Context;
                        import android.view.MotionEvent;
                        import android.app.Activity;
                        import android.view.View;
                        import android.view.ViewGroup;
                        import android.view.View.OnClickListener;
                        import android.widget.Button;
                        import android.view.ViewGroup.LayoutParams;
                        import android.widget.FrameLayout;
                        import   android.graphics.Color;
                        import   android.view.Gravity;
                        import android.os.Bundle;
                        import android.app.Application;
    
                        //////////////////////////////////////////
    
                        Button monBouton1;
    
                        private static final int MY_BUTTON1 = 9000;//useless here but can be //very useful in another cases, if you have a lot of buttons
    
                        FrameLayout fl;
                        Context context; 
                        Activity act;
                        boolean pressed = false;
                        float touchX;// for motionEvent
                        float touchY;//for motionEvent
    
    
                        private void setup() {
    
    
                          act = this.getActivity();
                          context = act.getApplicationContext();
    
    
    
                          //use the android button class::
    
                          monBouton1 = new Button(act);
                          monBouton1.setText("Bouton1  ajouté ");
                          monBouton1.setBackgroundColor(Color.RED);
                          monBouton1.setId(MY_BUTTON1);
    
                          // create some listener 
    
                          OnClickListener oclMonBouton = new OnClickListener() {
    
                            public void onClick(View v) {
    
                              println("clicked");
        pressed = true;
                              ///your save method+ pressed = false;
                            }
                          };
    
                          monBouton1.setOnClickListener(oclMonBouton);//add the listener to the button
    
    
                          //display button with parameters (using gravity)
    
                          fl = (FrameLayout)act.findViewById(0x1000);//since processing 3 you //are in a frame layout, and digging into p5 code i have found its id...
    
                          getActivity().runOnUiThread(new Runnable() {
    
                            public void run() {
                        //1== because you can add here (loop) a lot of buttons if you want
    
                              FrameLayout.LayoutParams params1 = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, Gravity.CENTER); 
    
    
                              fl.addView(monBouton1, params1);//adding the button to the view...
    
                            }
                          }
                          );
    
  • Merci beaucoup @akenaton -- yep, that works. It gives me somewhere to start.

  • edited January 2016 Answer ✓

    I use mousePressed() on Android .. it does work ...

    And the Ketai gestures are well worth trying ..

  • edited January 2016

    Yes, mousePressed() does work.

    Ketai does of course allow the creation of on-screen buttons. So far I have found them less intuitive to code than with APWidgets because you have to set a "target area" to press/touch on the screen. If you have a lot of buttons, working these out becomes very tedious - though it is doable.

    This isn't supposed to run, but does show the approach I used to code 6 buttons...

    void mousePressed() {
      {
        if ((mouseX > width/2) && (mouseY < 51)) {
          if (looping) noLoop();
          else loop();
        }
    
      if ((mouseX < width/4) && (mouseY > 51) && (mouseY < 91))
        v1 = v1 + 1;
      if (v1 > 3) {
        v1 = 3;
      }
    }
    
    if ((mouseX > width/4) && (mouseX < width/4*2) && (mouseY > 51) && (mouseY < 91))
      v1 = v1 - 1;
    if (v1 < 1) {
      v1 = 1;
    }
    
    if ((mouseX > width/4*2) && (mouseX < width/4*3) && (mouseY > 51) && (mouseY < 91))
      v2 = v2 + 1;
    if (v2 > 5) {
      v2 = 5;
    }
    
    if ((mouseX > width/4*3) && (mouseX < width) && (mouseY > 51) && (mouseY < 91))
      v2 = v2 - 1;
    if (v2 < 1) {
      v2 = 1;
    }
    
    if (mouseX < width/2) {
    

    ...

    And this to render the buttons...

    void drawUI() {
    
      pushStyle();
      textAlign(LEFT);
      textSize(20);
      fill(125);
      stroke(255);
      rect(5, 5, width/2 - 5, 50); //SAVE
      rect(width/2 + 5, 5, width/2 - 10, 50);
      rect(5, 60, width/4-5, 50);
      rect(width/4+5, 60, width/4 - 5, 50);
      rect(width/4*2+5, 60, width/4 - 5, 50);
      rect(width/4*3+5, 60, width/4 - 10, 50);
      fill(255);
      stroke(0);
      strokeWeight(1);
      text("BUTTON A", 25, 35);
      text("BUTTON B", (width/2 + 25), 35);
      text("BUTTON C", 25, 90);
      text("BUTTON D", (width/4 + 25), 90);
      text("BUTTON E", (width/4*2 + 25), 90);
      text("BUTTON F", (width/4*3 + 25), 90);
      popStyle();
    }
    
  • edited January 2016 Answer ✓

    Here's how I do it ... or at least partially. I have used an array list here to hold 6 buttons based on my SimpleButton class. Just get rid of the size() in setup() for android use.

    I see in your code you have some hard coded values like 51, 91 whereas I have set the width and height of my buttons based on display width. You may want to try this as it will make your buttons look the same size relative to display width on any phone.

        //declare an array of buttons
        ArrayList <SimpleButton> buttonList; 
    
        void setup() {
          size(400, 600); // java mode only ... 
          //create buttonList... 6 buttons here
          float buttonWidth = width/6; // or whatever ...
          float buttonHeight = width/6 ; // buttons will be square
          float yPos = height/4 ; //or whatever ...
          // instantiate the list
          buttonList = new ArrayList<SimpleButton>(); 
          // make the buttons
          for (int i=0; i<6; i++) {
            buttonList.add(new SimpleButton(i*buttonWidth, yPos, buttonWidth, buttonHeight, "b " + i));
          }
          textAlign(CENTER, CENTER);
        }
    
        void draw() {
          for (int i=0; i<6; i++) {
            SimpleButton button =  buttonList.get(i);
            button.display();
          }
        }
    
        void mousePressed() {
          for (int i=0; i<6; i++) {
            SimpleButton button =  buttonList.get(i);
            if (button.over()) {
              button.setActiveState(true);
            }
          }
        }
    
        void mouseReleased() {
          for (int i=0; i<6; i++) {
            SimpleButton button =  buttonList.get(i);
            if (button.over()) {
              button.setActiveState(false);
            }
          }
        }
    
        class SimpleButton {
    
          //Variables
          float x, y, w, h; //position, width and height of button
          String label;
          boolean activeState=false;
          color fillColour = color(125) ; //grey
          color borderColour = color(0) ; //black  
    
          //Constructor
          SimpleButton (float _x, float _y, float _w, float _h, String _label) {
            x=_x; 
            y=_y; 
            w=_w; 
            h=_h;
            label=_label ;
          }
    
          //Methods
    
          void display() {
            fill(fillColour);
            rect(x, y, w, h);
            fill(0);
            text(label, x, y, w, h);
          }//end
    
          boolean over() {
            if (mouseX>x && mouseX<x+w && mouseY>y && mouseY<y+h) {
              return true;
            } else {
              return false;
            }
          } //end over()
    
          void setActiveState(boolean _state){
            activeState = _state ;
            if(activeState) {
              fillColour = color(255,0,0); //red
            }
            else {
              fillColour = color(125); //grey
            }
          }
    
        }//END SimpleButton
    
  • Yes @hudson_m4000 that is a much neater, and more flexible, way of approaching buttons. The hard-coded way does indeed cause problems when switching between devices with different screen sizes.

  • edited January 2016

    Another 2 questions...

    1. A StringList would be the best way to "name" the buttons something other than 0, 1, 2, 3 etc?

    2. If I try to give each button a specific function, can I use something like:

    void mousePressed() { for (int i=0; i<6; i++) { SimpleButton button = buttonList.get(0); v1 = v1 + 1; if (v1 > 3) { v1 = 3; } } }

    This seems to not work. I am trying to tell the sketch to "get" the 1st button in the buttonList array...

  • Sorry, that piece of code ^ seems to not want to format as code :(

  • edited January 2016 Answer ✓

    @PDF197 You are in a for loop but not testing for which button is pressed. Try this

        void mousePressed() {
          int buttonID ; // temp variable to hold selected button (range 0-5)
          for (int i=0; i<6; i++) {
            //which button?
            SimpleButton button =  buttonList.get(i);
            if (button.over) {
              buttonID = i;
            }
          }//end i loop
    
          //code for each button
          switch(buttonID) {
          case 0: //first button
            v1 = v1 + 1;
            if (v1 > 3) {
              v1 = 3;
            }
            break;
          case 1: //second button
            // do whatever here
            break;
          case 2: //third button
              // do whatever here
            break;
          case 3: //fourth button
              // do whatever here
            break;
          case 4: //fifth button
              // do whatever here
            break;
          case 5: //6th button
              // do whatever here
            break;
          }//end switch
        }//end mousePressed
    

    For labelled buttons use a String array put at top of code before setup.

        String[] buttonLabels = {"one", "two", "three", "four", "five", "six"};
    

    Then when making the buttons ...

        buttonList.add(new SimpleButton(i*buttonWidth, yPos, buttonWidth, buttonHeight, buttonLabels[i]));
    
Sign In or Register to comment.