Howdy, Stranger!

We are about to switch to a new forum software. Until then we have removed the registration on this forum.

  • How to play 2 consecutive mp3 with MediaPlayer?

    I am trying to play two consecutive mp3 (the second starting when the first ends). Is it possible?

    At the moment I use a delay but this solution is far from being optimal. Thank you in advance

          act = this.getActivity();
          context = act.getApplicationContext();
    
          try {
            s1 = new MediaPlayer();
            s2 = new MediaPlayer();
    
            af1 = context.getAssets().openFd("sound1.mp3");
            af2 = context.getAssets().openFd("sound2.mp3");
    
            s1.setDataSource(af1.getFileDescriptor(), af1.getStartOffset(), af1.getLength());
            s2.setDataSource(af2.getFileDescriptor(), af2.getStartOffset(), af2.getLength());
    
            s1.prepare();// prepare the sound for playing/usage
            s2.prepare();
    
            s1.start();
            delay(800);  // <-------------- ugly!
            s1.release();
            s1 = null;
    
            s2.start();
            delay(600); // <---------------
            s2.release();
            s2 = null;
          }
          catch(IOException e) {
          }
    
  • Filepath Issue

    Not sure why that is happening in your case. Surface is one of the internal java classes that should be present in the core.jar. I have few suggestions:

    Go into your sketch folder and rename your manifest file. Build your code again and Processing should regenerate a new manifest.

    A second suggestion: If you run a simple sketch, similar to: https://android.processing.org/tutorials/getting_started/index.html does it work?

    Finally, try this: stream = getActivity().getAssets().open(filename);

    Kf

  • Video in Android Mode

    @flashbacker

    Yes, you need these imports and create a context (as you have done in your code above)

    import android.content.Context; import android.os.Build ;

    Context context;' Activity act;

    and in setup ...

    act = this.getActivity(); context = act.getApplicationContext();

  • Video in Android Mode

    @kfrajer

    I've actually managed to use hudson_m4000 code to confirm what the path of my video file should be. Problem even with this info, my processing sketch won't find my file. The following code (even if I know it can't show the video image) compile on my device, but return to the console "error loading transit.mp4":

    import android.media.MediaPlayer;
    import android.os.Environment;
    import android.app.Activity;
    import android.content.Context;
    MediaPlayer mp ;
    Context context ;
    Activity activity ;
    String statusText = "VIDEO INITIALIZING";
    String SDCard = new String(Environment.getExternalStorageDirectory().getAbsolutePath());
    //String SDCard = "/storage/3E07-120C/";
    
    void setup() {
      size(400,400);
      activity = this.getActivity();
      context = activity.getApplicationContext();
      mp = new MediaPlayer();
      println( SDCard);
      try {
        mp.setDataSource(SDCard + "machine.mp4");
        mp.prepare();
        mp.start();
        statusText = "VIDEO PLAYING";
      }
      catch (IOException e) {
        println("error loading transit.mp4");
      }
      fill(255); 
      textAlign(CENTER, CENTER);
    }
    

    This code can't compile:

    import android.media.MediaMetadataRetriever;
    import android.os.Handler;
    import android.os.HandlerThread;
    import android.os.Looper;
    import android.app.Activity;
    import android.view.ViewGroup;
    import android.view.View;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    import android.media.MediaMetadataRetriever;
    import android.media.MediaPlayer;
    import android.content.res.Resources;
    import android.content.res.AssetFileDescriptor;
    import android.content.res.AssetManager;
    import android.content.Context;
    
    AssetFileDescriptor afd;
    Context context;
    Activity act;
    SurfaceView mySurface;
    SurfaceHolder mSurfaceHolder;
    MediaMetadataRetriever metaRetriever;
    MediaPlayer mMediaPlayer;
    
    void setup() {
      size(400, 400, P2D);
      act = this.getActivity();
      context = act.getApplicationContext();
      Looper.prepare();
      mMediaPlayer = new MediaPlayer();
      try {
        afd = context.getAssets().openFd("machine_compr.mp4");
        MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
        metaRetriever.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
        String height = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT); 
        if (int(height) < 2) {
          throw new IOException();
        }
      }
      catch (IllegalArgumentException e) {
        e.printStackTrace();
      }
      catch (IllegalStateException e) {
        e.printStackTrace();
      } 
      catch (IOException e) {
        e.printStackTrace();
      }
    
      mySurface = new SurfaceView(act);
      mSurfaceHolder = mySurface.getHolder();
      mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
      mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
        @Override
          public void surfaceCreated(SurfaceHolder surfaceHolder) {
          mMediaPlayer.setDisplay(surfaceHolder);
        }
    
        @Override
          public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) {
          mMediaPlayer.setDisplay(surfaceHolder);
        }
    
        @Override
          public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        }
      }
      );
      startVideo();
    }
    
    void startVideo() {
      act.runOnUiThread(new Runnable() {
        public void run() {
          try {
            mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
            mSurfaceHolder = mySurface.getHolder();
            mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            mMediaPlayer.prepare();
    //        act.addContentView(mySurface, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT));
            act.addContentView(mySurface, new ViewGroup.LayoutParams(400,400));
            if (mMediaPlayer.isPlaying() == false) {
              mMediaPlayer.start();
            }
          }
          catch (IllegalArgumentException e) {
            e.printStackTrace();
          }
          catch (IllegalStateException e) {
            e.printStackTrace();
          } 
          catch (IOException e) {
            e.printStackTrace();
          }
        }
      }
      );
    };
    
    void draw() {
    }
    
    void onPause() {
      if (mMediaPlayer!=null) {
        mMediaPlayer.release();
        mMediaPlayer = null;
      }
      super.onPause() ;
    }
    
    void onStop() {
      if (mMediaPlayer!=null) {
        mMediaPlayer.release();
        mMediaPlayer = null;
      }
      super.onStop() ;
    }
    
    void onDestroy() {
      if (mMediaPlayer!=null) {
        mMediaPlayer.release();
        mMediaPlayer = null;
      }
      super.onDestroy() ;
    }
    
    void onResume() {
      super.onResume() ;
    }
    

    and the console says it's because file couldn't be loaded

    OpenGL error 1280 at bot beginDraw(): invalid enum
    java.io.FileNotFoundException: machine_compr.mp4
        at android.content.res.AssetManager.openAssetFd(Native Method)
        at android.content.res.AssetManager.openFd(AssetManager.java:334)
        at processing.test.android_nativeplayer.android_nativeplayer.setup(android_nativeplayer.java:66)
        at processing.core.PApplet.handleDraw(PApplet.java:1801)
        at processing.opengl.PSurfaceGLES$RendererGLES.onDrawFrame(PSurfaceGLES.java:264)
        at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1590)
        at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1286)
    FATAL EXCEPTION: main
    Process: processing.test.android_nativeplayer, PID: 12773
    java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.FileDescriptor android.content.res.AssetFileDescriptor.getFileDescriptor()' on a null object reference
        at processing.test.android_nativeplayer.android_nativeplayer$2.run(android_nativeplayer.java:110)
        at android.os.Handler.handleCallback(Handler.java:815)
        at android.os.Handler.dispatchMessage(Handler.java:104)
        at android.os.Looper.loop(Looper.java:207)
        at android.app.ActivityThread.main(ActivityThread.java:5765)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)
    OpenGL error 1285 at bot endDraw(): out of memory
    

    I'll maybe try a post on the new forum, but there's so much ressource here, it felt more accurate to post here rather than create a new post which would point towards here...

  • Closing app on Backpress using Android Processing

    I've just finished doing test doing "public void onPause, onStop, onResume and onStart" and also considered using "this.getActivity()" and System.exit(0);".

    The result are the following:

    (1) Based on the test, using "onPause" and "onStop" works. Also "System.exit(0);" should be used. It disconnects the bluetooth connection of both the application and the target device.

    (2) It keeps the application in the background and reconnects bluetooth connection with target paired device when re-accessed.

    But there is only one issue. When accessing app in the background, when displayed using the background applications button, the application does not respond on the first tap and displays or opens a different app. But reconnects on the second tap when app is re-accessed again.

    No major issue though, but unable to access the application on the first tap is not a good quality. The issue only arises when the background application is pressed, but no issues with the home and back button.

  • Closing app on Backpress using Android Processing

    I've been doing tests, and I thought of a solution. Indicated are the following observations.

    (1)Pressing the "background apps button" and the "home button" places the application on the background without disconnecting the bluetooth connection with the target device.

    (2)Pressing the "back button" places the application on the background disconnecting the bluetooth connection with the target device. A function placing the application onPause.

    The problem occurs when the back button is pressed due to the reason that the app disconnects the bluetooth but the target device does not disconnect its connection unless the app completely closes, which only can be done manually when accessing the application on the "backround applications" and closing it there.

    To efficiently reconnect the bluetooth connection of the app and the target device, the application should be completely closed, to also disconnect the bluetooth with the target device, but unfortunately, it is not possible. This makes "System.exit(0);" and "this.getActivity().finish();" not applicable. Also I tried removing the onBackpressed codes, and it works on (1) and (2) on default.

    Is there a way to do the other way around since it works on (1) and (2) on default. That onBackpressed, we avoid the application from disconnecting bluetooth connection?

    The truth is I already done everything I could, and I already want to give up. The only option that is left is how would I be able to work on the Bakpress button wothout disconnecting the bluetooth connection like the onPause.

  • Closing app on Backpress using Android Processing

    I forgot how to put the codes, but the issues started on the indicated codes, for there were a lot of changes done after changing codes to adapt for P3. I am not hoping much for a solution anymore, but just in case, you would see the error.

    // *** For Bluetooth Features *** // public class myOwnBroadcastReceiver extends BroadcastReceiver { ConnectToBluetooth connectBT;

    @Override public void onReceive(Context context, Intent intent) { String action=intent.getAction();

    if(BluetoothDevice.ACTION_FOUND.equals(action)){ String discoveredDeviceName = intent.getStringExtra(BluetoothDevice.EXTRA_NAME); BluetoothDevice discoveredDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); foundDevice=true;

    if(discoveredDeviceName.equals("HMSoft")) {//name of device ToastMaster("Connecting you Now !!!"); connectBT = new ConnectToBluetooth(discoveredDevice); new Thread(connectBT).start();

    } else { ToastMaster("Please Turn on Target Device"); ToastMaster("Please Turn on Target Device"); ToastMaster("Please Turn on Target Device"); ToastMaster("Please Turn on Target Device"); ToastMaster("Please Turn on Target Device"); } }

    if(BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)){ ToastMaster("Already CONNECTED with Target Device"); while(scSocket==null){ } BTisConnected=true; if(scSocket!=null){ sendReceiveBT = new SendReceiveBytes(scSocket); new Thread(sendReceiveBT).start(); String red = "r"; byte[] myByte = stringToBytesUTFCustom(red); sendReceiveBT.write(myByte); } } } }

    // *** for Communication *** // public static byte[] stringToBytesUTFCustom(String str) { char[] buffer = str.toCharArray(); byte[] b = new byte [buffer.length << 1]; for (int i = 0; i < buffer.length; i++) { int bpos = i << 1; b[bpos] = (byte) ((buffer[i]&0xFF00)>>8); b[bpos + 1] =(byte) (buffer[i]&0x00FF); } return b; }

    ////////////////////////////////////////////////////////////////////////////////////////////// public void onBackPressed() { System.exit(0); } ////////////////////////////////////////////////////////////////////////////////////////////

    public class ConnectToBluetooth implements Runnable{ private BluetoothDevice btShield; private BluetoothSocket mySocket = null; private UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

    public ConnectToBluetooth(BluetoothDevice bluetoothShield) { btShield = bluetoothShield;

    try{ mySocket = btShield.createRfcommSocketToServiceRecord(uuid); } catch(IOException createSocketException){ Log.e("ConnectToBluetooth", "Error with Socket"); } }

    public void run() { bluetooth.cancelDiscovery();

    try{ mySocket.connect(); scSocket=mySocket; } catch (IOException connectException){ Log.e("ConnectToBluetooth", "Error with Socket Connection");

    try{ mySocket.close(); } catch(IOException closeException){ } return; } }

    public BluetoothSocket getSocket() { return mySocket; }

    public void cancel() { try { mySocket.close(); } catch (IOException e) { } } }

    // *** For GUI Communication *** // private class SendReceiveBytes implements Runnable { private BluetoothSocket btSocket; private InputStream btInputStream = null; private OutputStream btOutputStream = null; String TAG = "SendReceiveBytes"; public SendReceiveBytes(BluetoothSocket socket) { btSocket = socket; try { btInputStream = btSocket.getInputStream(); btOutputStream = btSocket.getOutputStream(); } catch (IOException streamError) { Log.e (TAG, "Error when getting input or output Stream"); } }

    public void run () { byte[] buffer = new byte [1024]; int bytes; while (true) { try { bytes = btInputStream.read(buffer); mHandler.obtainMessage (MESSAGE_READ, bytes, -1, buffer) .sendToTarget(); } catch (IOException e) { Log.e(TAG, "Error reading from btInputStream"); break; } } }

    public void write(byte[] bytes) {
    try { btOutputStream.write(bytes); } catch (IOException e) { Log.e(TAG, "Error when writing to btOutputStream"); } }

    public void cancel() { try { btSocket.close(); } catch (IOException e) { Log.e(TAG, "Error when closing the btSocket"); } } }

    void ToastMaster(String textToDisplay) { Toast myMessage = Toast.makeText(this.getActivity().getApplicationContext(), textToDisplay, Toast.LENGTH_LONG); myMessage.setGravity(Gravity.CENTER, 0, 0); myMessage.show(); }

  • Closing app on Backpress using Android Processing

    @myrds===

    without knowing how you have created your blueTooth conn. it's difficult to answer...Yet, supposing that you have a broadcastReceiver running (called eg myDiscoverer) you have to code something like that::

          public void onPause(){
                    super.onPause();
    
                    if(myDiscoverer !=null){
                    getActivity().unregisterReceiver(myDiscoverer);
                    println("je désenregistre");
                    myDiscoverer=null;
                    }else{
                      println("désenregistré");
                    }
    
                    }
    
  • Closing app on Backpress using Android Processing

    @myrds===

    try that

    this.getActivity().finish();

    • though i cannot see any reason to code the Back button because it is supposed to "finish" the current activity & put it in te background, which meas that "quitting" or "exiting" has no sense in the android world....
  • Processing codes used in version 3.0, not working on version 3.3.6

    I already found the solution to the problem, it was not on the android mode version it is not even in the manifest. The code syntax I used in the processing 3.0 is

    startActivityForResult(requestBluetooth, 0);

    and this syntax worked after building, but on the processing 3.3.7, I changed the syntax to

    this.getActivity().startActivityForResult(requestBluetooth, 0);

    which by using that syntax, I was able to successfully build the app to my android device. I already experienced fixing the codes with every upgraded version of processing. From processing 2 to processing 3.0 to processing 3.3.7. I hope that this would be the last one wherein processing version upgrade won't affect previous codes. The android device and version that I used in all the versions did not change.

  • problem with ketai gps

    @erwrow===

    i dont know what is happening for your app; what i know is that there are a lot of cases in which for various reasons ketai does not work. So, as ketai is only a wrapper for android, i think that it is more sure to use android API.

    As for location there are many ways to do that; you can use googlePlayservice or code yourself : firstly you create an instance of LocationManager which is a system service; after that you create a Location object with your LocationManager and now you can get your location (double latitude, double longitude): snippet here::

        double latitude, longitude;
    
    
        LocationManager locationMan = (LocationManager)this.getActivity().getSystemService(Context.LOCATION_SERVICE); 
        Location location = locationMan.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        longitude = location.getLongitude();
        latitude = location.getLatitude();
    

    In order to be more efficient you can add a listener to your locationManager, implementing the required methods and commenting the 2 lines where it is called for latitude && longitude.

            LocationListener locationListener= new LocationListener() {
                public void onLocationChanged(Location location) {
                    longitude = location.getLongitude();
                    latitude = location.getLatitude();
                }
    
                 public void onProviderDisabled(String provider) {
            //alert the user:Called when the provider is disabled by the user: "are you sure?"
                }
    
                //@Override
                public void onProviderEnabled(String provider) {
    

    //Called when the provider is enabled by the user. }

                //@Override
                public void onStatusChanged(String provider, int status, Bundle extras) {
    

    //could be OUT_OF_SERVICE, AVAILABLE, TEMPORARLY_UNAVAILABLE //alert the user } };

    locationMan.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 10, locationListener);// the 2 integer values define the time and distance, in this case each 2" and each 10 meters.
    

    i have used this code or rather this kind of code for a lot of times and i am sure that it works; of course you must have the (3) permissions granted (and test that at runtime); of course also before instantiating the LocationManager you have to test the network (is wifi or mobile available...) and choose the provider.

  • [Android] How to create notifications, even when the app is closed.(2)

    [REFERENCE LINK] https://forum.processing.org/two/discussion/4429/notifications-in-android-mode https://forum.processing.org/two/discussion/16840/how-to-create-notifications-even-when-the-app-is-closed

    How to create notifications, even when the app is closed.

    Is it impossible with the Processing(android mode) program?

    https://developer.android.com/guide/topics/ui/notifiers/notifications.html#CreateNotification

    [EXAM]

    import android.view.MotionEvent; 
    import android.content.Context;
    import android.app.Notification;
    import android.app.NotificationManager;
    import android.app.Activity;
    
    Activity act;
    NotificationManager gNotificationManager;
    Notification gNotification;
    long[] gVibrate = {0,250,50,125,50,62};
    Context ctx;
    
    void setup() {
      size(displayWidth, displayHeight);
    
    
    }
    
    void draw() {
    
    }
    
    
    void onResume() {
      super.onResume();
      // Create our Notification Manager:
      gNotificationManager = (NotificationManager) this.getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
      // Create our Notification that will do the vibration:
      gNotification = new Notification();
      // Set the vibration:
      gNotification.vibrate = gVibrate;
    }
    
    public boolean surfaceTouchEvent(MotionEvent event) {
      // If user touches the screen, trigger vibration notification:
      gNotificationManager.notify(1, gNotification);
      return super.surfaceTouchEvent(event);
    }
    

    It does not work.

  • Different sizes on different devices

    @OliverC===

    screens are classified by android according to pixels density; medium density is 160dpi: so, in order to adapt your app to the user screen you have to use (with AS and xml) dp (or dip) units which are "abstracted" units and mean "density independant pixels"; with P5 as you cannot use these units you have to "transform" your pixels in dip (or dp); that is easy, it's like "scaling".

    • First you get the screen density by code, writing float fact = getActivity().getResources().getDisplayMetrics().density;

    • it wil return some factor depending of the phone; if you are using a "medium 160dpi phone" it will return 1.0; if you are using a low density screen it will return 0.75; if you are using a xxhdpi phone it will return 2.0...and so on;

    • now scaling your buttons or textSize() or.... is easy: a button with 20px width appears 20px width on a 160dpi phone but it will appear as 10 on a Xhdpi phone: so you have to give it a size of 20*2.0. That s' all.

  • KetaiList

    Not sure about margins, but you should explore

    https://developer.android.com/reference/android/view/ViewGroup.LayoutParams.html

    This is in

    parent.getActivity().addContentView(self, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, 
              ViewGroup.LayoutParams.FILL_PARENT));
    

    You can adjust the width and the height there. Then you should be able to call setX and setY, functions associated to the ListView list. No time to test right now, hopefully it gives you a lead of what to do.

    Kf

    self.setY(500);
    parent.getActivity().addContentView(self, new ViewGroup.LayoutParams(width/2,height/2);
    
  • Scrollable image with ScrollView

    @noel===

    code snippet for android webview from local files and your image "panorama" - (put the.html+ the image in the data folder or change the code as it is explained if it is in a subfolder)::

        import android.content.res.AssetManager;
        import android.webkit.WebViewClient;
        import android.os.Looper;
        import android.content.Context;
        import android.view.ViewGroup.LayoutParams;
        import android.webkit.WebView;
        import android.view.ViewGroup;
        import android.app.Activity;
        import android.widget.RelativeLayout;
        import android.widget.FrameLayout;
        import java.io.File;
        import android.os.Bundle;
        import android.os.Environment;
    
    
    
        FrameLayout fl;
        Activity act;
        WebView web;
        Context context;
        WebViewClient wbc;///if you want to use chrome
        File[] files;//if you want to list files
        String[] filesPath;//if you want to list subfolders
    
    
    
        void settings(){
          fullScreen();
        };
    
        public void onStart() {
          super.onStart();
    
          act = this.getActivity();
          wbc = new WebViewClient();
          web = new WebView(act);
          web.setLayoutParams(new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT));
          web.setWebViewClient(wbc);
          web.getSettings().setJavaScriptEnabled(true);
          //loadFiles("autredos");//au cas où il y aurait un sous dossier "autredos" dans data
          web.loadUrl("file:///android_asset/grandeimage.html");//change that for one of the result from filesPath for subfolders; else this file must be in the data folder
          fl = (FrameLayout)act.getWindow().getDecorView().getRootView();
          fl.addView(web);
        };
    
        void setup(){
        background(255,0,0);
        };
    
        void draw(){
           background(255,0,0);
        };
    
        String[] loadFiles(String folderName_){//useless in most of cases
    
    
          AssetManager assetManager = act.getAssets();
          try{
            filesPath = assetManager.list(folderName_);//for files path in subfolder "autredos"
    
           files = new File[filesPath.length];//for files
    
    
             for(int i=0; i<filesPath.length; i++){
    
             files[i] = new File(folderName_+"/" + filesPath[i]);
             println("les fichiers d'autredos sont====" +files[i]);
            }
    
    
          }
          catch(IOException ex){
               System.out.println (ex.toString());   
          }
    
          return filesPath;
        };
    
  • Scrollable image with ScrollView

    A new demo. If you load images from internet, you need the internet permission.

    Kf

    //===========================================================================
        // IMPORTS:
    
    import android.app.Activity;
    import android.content.Context;
    import android.widget.FrameLayout;
    //import android.app.Fragment;
    
    import android.os.Environment;
    import android.graphics.Color;
    import android.widget.Toast;
    import android.os.Looper;
    import android.view.WindowManager;
    import android.os.Bundle;
    import android.view.ViewParent;
    import android.view.ViewGroup;
    import android.view.View;
    import android.widget.RelativeLayout;
    import android.widget.LinearLayout;
    import android.view.LayoutInflater;
    import android.R.string;
    
    import android.R;
    import android.widget.ImageView;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.net.Uri;
    import android.util.Log;
    import android.widget.ScrollView;
    import android.widget.Button;
    
    
        //===========================================================================
    // FINAL FIELDS:
    final int imageID=12345;
    
    //===========================================================================
    // GLOBAL VARIABLES:
    
    Activity act;
    Context mC;
    
    FrameLayout fl;
    ScrollView sv;
    int imageID1=-1;
    int imageID2=-1;
    int imageID3=-1;
    
    
    ArrayList<PImage> imgCon;
    
    PImage img1, img2, img3;
    int currIdx=-1;
    
    
    //===========================================================================
    // PROCESSING DEFAULT FUNCTIONS:
    
    void setup() {
      fullScreen();
      orientation(PORTRAIT);
    
      act = this.getActivity();
      Looper.prepare();
    
      textAlign(CENTER, CENTER);
    
      fill(255);
      strokeWeight(2);
      textSize(32);
    
      imgCon = new ArrayList<PImage>();
    
      imgCon.add(initImage(width, int(height*0.80), "KlEo"));
      imgCon.add(initImage(width, int(height*1.25), "xSiNe")); 
      imgCon.add(initImage(width, int(height*1.50), "DRAkeN")); 
    
      //  *****  FOR the next images one needs to enable INTERNET permissions
    
      //PImage extra1=requestImage("https://vignette.wikia.nocookie.net/vsbattles/images/a/ad/Alduin.jpg/revision/latest?cb=20140811032839");  //dragon
      PImage extra2=requestImage("https://upload.wikimedia.org/wikipedia/commons/c/ce/Black-headed_oriole,_Oriolus_larvatus,_at_Mapungubwe_National_Park,_Limpopo,_South_Africa_(18201359415).jpg");  //Yellow bird
      PImage extra3=requestImage("http://78.media.tumblr.com/ff9912bcaa6963631a6a205ae7be46a5/tumblr_mxarraaVgz1shaozko1_1280.jpg");
      PImage extra4=requestImage("http://www.shorpy.com/files/images/SHORPY_4a08044a.jpg");  //NY building
    
      while ( extra2.width<=1 || extra3.width<=1 || extra4.width<=1 ) {
        if(frameCount%90==0) println(extra2.width,extra3.width,extra4.width);
        delay(50);
      }
    
    
      extra2.loadPixels();
      extra2=extra2.get(0, 0, min(width, extra2.width), extra2.height);
      extra2.updatePixels();
    
      extra3.loadPixels();
      extra3=extra3.get(0, 0, width, extra3.height);
      //extra3.resize(width, extra3.height);
      extra3.updatePixels();
    
      //imgCon.add(extra1);
      imgCon.add(extra2);
      imgCon.add(extra3);
      imgCon.add(extra4);
      //imgCon.add(extra5);
    
      for (PImage q : imgCon) {
        println(q.width, q.height);
      }
    
    
      currIdx=0;
      swapImage();
    }
    
    void draw() {
    
      text("Scroll View Demo showing now "+currIdx, width>>1, height/40.0);
      text("Size of selected iamge "+imgCon.get(currIdx).width+"x"+imgCon.get(currIdx).height, width>>1, height/16.0);
    }
    
    void mouseReleased() {
      //swapImage();
    }
    
    void swapImage() {
    
      background(random(70, 144));
      currIdx=(currIdx+1)%imgCon.size();
    
      act.runOnUiThread(new Runnable() {
        @ Override
          public void run() {
    
          ImageView imgv= (ImageView)  act.findViewById(imageID); 
          imgv.setImageBitmap((Bitmap)imgCon.get(currIdx).getNative());
        }
      }
      );
    }
    
    
    //===========================================================================
    // OTHER FUNCTIONS:
    
    //Creates an image with a color gradient as background and a ellipse of random size
    //placed at a random location. The label is placed inside the ellipse.
    PImage initImage(int w, int h, String label) {
      PImage aimg =createImage(w, h, ARGB);
    
      int s=w*h;
      float lower=random(225);
      float delta=25;
      colorMode(HSB, 255);
    
      aimg.loadPixels();
      for (int i=0; i<s; i++)
        aimg.pixels[i]=color(int(lower+delta*i*1.0/s), 255, 255);//color(random(upper), random(50, 200), random(upper,255));
      aimg.updatePixels();
    
      int diameter=int(w*random(0.35, 0.70));
      float px=random(diameter, width-diameter);
      float py=random(diameter, height-diameter);
    
      PGraphics con =createGraphics(w, h, JAVA2D);
      con.beginDraw();
      con.image(aimg, 0, 0);
    
      con.fill(255-lower, 250, 250);
      con.noStroke();
      con.ellipse(w-px, h-py, diameter/2.0, diameter/2.0);
      con.ellipse(px, py, diameter, diameter);
    
      con.textAlign(CENTER, CENTER);
      con.colorMode(HSB, 255);
      con.fill(lower, 255, 255);
      con.textSize(max(36, w/80.0));
      con.text(label, px, py);
      con.text(label, px+1, py+1);  //Bold effect
    
      con.endDraw();
      return con.get();
    }
    
    //===========================================================================
    // ANDROID ACTIVITY LIFECYCLE'S FUNCTIONS:
    
    
    //  @@@@@@@@@@@@
    @Override
      public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
    
      act = this.getActivity();
      mC= act.getApplicationContext();
    
      // OOOOOOOOOOOOOOOO---------------------------OOOOOOOOOOOOOOOO
    
      // OOOOOOOOOOOOOOOO---------------------------OOOOOOOOOOOOOOOO
    
    
      Button switchButton= new Button(act);
      switchButton.setLayoutParams(new RelativeLayout.LayoutParams(width>>2,int(height/13.0)));
      switchButton.setTextSize(10);
      //switchButton.setTextColor(Color.rgb(220,220,220));
      switchButton.setText ("Next Image");
      switchButton.setX(width*0.60);
      switchButton.setY(height*0.1);
      switchButton.setOnClickListener(new View.OnClickListener(){    
        public void onClick(View V){ 
          swapImage(); 
        }
      });
    
      ImageView imgView = new ImageView(act);
      imgView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
      imgView.setId(imageID); //imgView1.generateViewId()
    
    
      LinearLayout linLay=new LinearLayout(act);
      linLay.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); 
      linLay.setOrientation(LinearLayout.VERTICAL);  
      linLay.addView(imgView);
    
     int svHeight=int(height*0.70);
      sv = new ScrollView(act);
      sv.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, svHeight));  
      sv.setVerticalScrollBarEnabled(true);  
      sv.setY(height-svHeight);  
      sv.addView(linLay);
    
    
      // OOOOOOOOOOOOOOOO---------------------------OOOOOOOOOOOOOOOO
    
      //                 @@@@@@@@@@@@@@@@@@@@@@@@@@@
    
      // OOOOOOOOOOOOOOOO---------------------------OOOOOOOOOOOOOOOO
    
    
      fl = (FrameLayout)act.findViewById(R.id.content);
      fl.addView(switchButton);
      fl.addView(sv);
    }
    
  • Scrollable image with ScrollView

    Not sure what is causing the problem in your case. I just tested the app in an emulator and it worked. I have to say that my code was not adapted to different screen resolutions. I modified the code to do so. I notice there is also a bug/undesirable features that if you press on the upper section of your screen, it will trigger the button. Not a big deal in this demo, but it is still a pain the the place where everybody knows.

    Below it shows the scrolling action.

    Kf

    Screenshot_1521531922

    Screenshot_1521531925

    Screenshot_1521531928

    //===========================================================================
    // IMPORTS:
    
    import android.app.Activity;
    import android.content.Context;
    import android.widget.FrameLayout;
    //import android.app.Fragment;
    
    import android.os.Environment;
    import android.graphics.Color;
    import android.widget.Toast;
    import android.os.Looper;
    import android.view.WindowManager;
    import android.os.Bundle;
    import android.view.ViewParent;
    import android.view.ViewGroup;
    import android.view.View;
    import android.widget.RelativeLayout;
    import android.widget.LinearLayout;
    import android.view.LayoutInflater;
    import android.R.string;
    
    import android.R;
    import android.widget.ImageView;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.net.Uri;
    import android.util.Log;
    import android.widget.ScrollView;
    import android.widget.Button;
    
    
    //===========================================================================
    // FINAL FIELDS:
    
    
    //===========================================================================
    // GLOBAL VARIABLES:
    
    Activity act;
    Context mC;
    
    FrameLayout fl;
    ScrollView sv;
    int imageID1=-1;
    int imageID2=-1;
    int imageID3=-1;
    
    PImage img1, img2, img3;
    int curr=-1;
    
    int basicImageSize=0;
    int thumbNailSize=0;
    
    //===========================================================================
    // PROCESSING DEFAULT FUNCTIONS:
    
    void setup() {
      fullScreen();
      orientation(PORTRAIT);
      //orientation(LANDSCAPE;)
    
      act = this.getActivity();
      Looper.prepare();
    
      textAlign(CENTER, CENTER);
      //rectMode(CENTER);
    
      fill(255);
      strokeWeight(2);
      textSize(max(16,width/30.0));
    
      basicImageSize=int(min(width,height)/4.0);
      thumbNailSize= int(basicImageSize/6.0);
    
    
    
      img1=initImage(basicImageSize*1, basicImageSize*3, ARGB);//loadImage("pic40.jpg");
      img2=initImage(basicImageSize*2, basicImageSize*3, ARGB); 
      img3=initImage(basicImageSize*3, basicImageSize*3, ARGB);
    
      curr=0;
    }
    
    void draw() {
    
      text("Scroll View Demo showing now "+curr, width>>1, thumbNailSize);
      text("Size of selected on left "+(basicImageSize*(curr+1))+"x900", width>>1, thumbNailSize*3);
    }
    
    void mouseReleased() {
    
      //if (mouseY>height>>2)    return;
    
      curr=(curr+1)%3;
    
      background(88);
    
      fill(255);
      noStroke();
      rect(0.80*thumbNailSize, thumbNailSize*0.80+thumbNailSize*5*curr, thumbNailSize*4.5, thumbNailSize*4.5);
    
      image(img1, thumbNailSize, thumbNailSize, thumbNailSize*4, thumbNailSize*4);
      image(img2, thumbNailSize, thumbNailSize*6, thumbNailSize*4, thumbNailSize*4);
      image(img3, thumbNailSize, thumbNailSize*11, thumbNailSize*4, thumbNailSize*4);
    
    
    
      act.runOnUiThread(new Runnable() {
        @ Override
          public void run() {
    
          ImageView imgv1= (ImageView)  act.findViewById(imageID1); 
          ImageView imgv2= (ImageView)  act.findViewById(imageID2); 
          ImageView imgv3= (ImageView)  act.findViewById(imageID3); 
    
    
          if (curr==0) {
            imgv1.setImageBitmap((Bitmap)img1.getNative()); 
            imgv2.setImageBitmap((Bitmap)img2.getNative()); 
            imgv3.setImageBitmap((Bitmap)img3.getNative());
          } else if (curr==1) {          
            imgv1.setImageBitmap((Bitmap)img2.getNative()); 
            imgv2.setImageBitmap((Bitmap)img3.getNative()); 
            imgv3.setImageBitmap((Bitmap)img1.getNative());
          } else if (curr==2) {          
            imgv1.setImageBitmap((Bitmap)img3.getNative());  
            imgv2.setImageBitmap((Bitmap)img1.getNative()); 
            imgv3.setImageBitmap((Bitmap)img2.getNative());
          }
        }
      }
      );
    }
    
    
    //===========================================================================
    // OTHER FUNCTIONS:
    
    PImage initImage(int w, int h, int mode) {
      PImage aimg =createImage(w, h, mode);
    
      int s=w*h;
      float lower=random(225);
      float delta=25;
      colorMode(HSB, 255);
    
      aimg.loadPixels();
      for (int i=0; i<s; i++)
        aimg.pixels[i]=color(int(lower+delta*i*1.0/s), 255, 255);//color(random(upper), random(50, 200), random(upper,255));
      aimg.updatePixels();
      return aimg;
    }
    
    
    
    //===========================================================================
    // ANDROID ACTIVITY LIFECYCLE'S FUNCTIONS:
    
    
    @Override
      public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
    
      act = this.getActivity();
      mC= act.getApplicationContext();
    
      // OOOOOOOOOOOOOOOO---------------------------OOOOOOOOOOOOOOOO
    
      // OOOOOOOOOOOOOOOO---------------------------OOOOOOOOOOOOOOOO
    
    
      Button switchButton= new Button(act);
      switchButton.setLayoutParams(new RelativeLayout.LayoutParams(width>>2,150));
      switchButton.setTextSize(10);
      //switchButton.setTextColor(Color.rgb(220,220,220));
      switchButton.setText ("Show next");
      switchButton.setX(width*0.60);
      switchButton.setY(200);
      switchButton.setOnClickListener(new View.OnClickListener(){
        public void onClick(View V){
    
          mouseReleased();
    
        }
      });
    
      ImageView imgView1 = new ImageView(act);
      imgView1.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
      imgView1.setId(imageID1=imgView1.generateViewId());
    
    
      ImageView imgView2 = new ImageView(act);
      imgView2.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
      imgView2.setId(imageID2=imgView2.generateViewId());
    
    
      ImageView imgView3 = new ImageView(act);
      imgView3.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
      imgView3.setId(imageID3=imgView3.generateViewId());
    
    
      LinearLayout linLay=new LinearLayout(act);
      linLay.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); 
      linLay.setOrientation(LinearLayout.VERTICAL);  
      linLay.addView(imgView1);
      linLay.addView(imgView2);
      linLay.addView(imgView3);
    
      sv = new ScrollView(act);
      sv.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,height));  //, LinearLayout.LayoutParams.WRAP_CONTENT)); // ,height-int(displayHeight/8.0)));  
      sv.setVerticalScrollBarEnabled(true);  
      sv.setY(int(displayHeight/8.0));  
      sv.addView(linLay);
    
    
      // OOOOOOOOOOOOOOOO---------------------------OOOOOOOOOOOOOOOO
    
      //                 @@@@@@@@@@@@@@@@@@@@@@@@@@@
    
      // OOOOOOOOOOOOOOOO---------------------------OOOOOOOOOOOOOOOO
    
    
      fl = (FrameLayout)act.findViewById(R.id.content);
      fl.addView(switchButton);
      fl.addView(sv);
    }
    
    //  @@@@@@@@@@@@
    @Override 
      public void onStart() {
      super.onStart();
    }
    
    //  @@@@@@@@@@@@
    @Override 
      public void onResume() {
      super.onResume();
    
      act = this.getActivity();
      mC= act.getApplicationContext();
    
    }
    
  • KetaiList

    Currently, most of the job is done in the init() function. If you want to change something, you are better off writing your own class where you define your own changes before the list is displayed.

    What kind of padding do you want to add? You mentioned about changing text and background color... anything else?

    For changes in the ListView, consult: https://developer.android.com/reference/android/widget/ListView.html

    Ketai is a library that allows you to easily use objects and functionalities provided by the Android API. It is doing all the heavy work for you at a cost of less flexibility aka. no customization. For anybody that wants to modify the ketai list demo, they are better off to write it from scratch by adding an extra layout to customize its objects. For instance, the text color of the list could be different than the text color of the title.

    More on the technical side: The library's init() and the adapter object are private members, which means they cannot be accessed (easily). For the amount of code it saves you there and the effort to introduce changes, you are better off doing it on your own, exactly what you are doing above (Yes, extending the class would not work). I will create a ticket in ketai requesting making those items public but it will not give you the flexibility you are looking for in the long run as the current layout of the code wouldnt allow use to reuse their code. Below is my demo demonstrating one of the changes you are looking for.

    Kf

    //REFERENCES: https:// stackoverflow.com/questions/4533440/android-listview-text-color
        //REFERENCES: https:// stackoverflow.com/questions/3663745/what-is-android-r-layout-simple-list-item-1
        //REFERENCES: https:// developer.android.com/reference/android/widget/ArrayAdapter.html
        //REFERENCES: https:// github.com/ketai/ketai/blob/master/src/ketai/ui/KetaiList.java
        //REFERENCES: http:// ketai.org/examples/ui/
    
    //INSTRUCTIONS:
    //         *--  You get two different lists in this sketch.
    //         *--  Ok, the list are the same but they have different
    //         *--  text color. Tapping on the upper half of the sketch
    //         *--  makes the text color blue. Otherwise, it uses the 
    //         *--  custom defined color.
    
    //===========================================================================
    // IMPORTS:
    
    import android.app.Activity;
    import android.content.Context;
    import android.widget.FrameLayout;
    //import android.app.Fragment;
    
    import android.os.Environment;
    import android.graphics.Color;
    import android.widget.Toast;
    import android.os.Looper;
    import android.view.WindowManager;
    import android.os.Bundle;
    import android.view.ViewParent;
    import android.view.ViewGroup;
    import android.view.View;
    import android.widget.RelativeLayout;
    import android.view.LayoutInflater;
    import android.R.string;
    
    
    //===========================================================================
    // FINAL FIELDS:
    
    
    //===========================================================================
    // GLOBAL VARIABLES:
    
    Activity act;
    Context mC;
    
    SelectionKList selectionlist;
    ArrayList<String> colorlist; 
    color currentColor;
    
    //===========================================================================
    // PROCESSING DEFAULT FUNCTIONS:
    
    void setup() {
      //size(400,600);
      fullScreen();
      orientation(PORTRAIT);
      //orientation(LANDSCAPE;)
    
      act = this.getActivity();
      Looper.prepare();
    
      textAlign(CENTER, CENTER);
      rectMode(CENTER);
    
      fill(255);
      strokeWeight(2);
      textSize(32);
    
      currentColor=color(0);
    
      colorlist = new ArrayList<String>();
      colorlist.add("Black");
      colorlist.add("Red");
      colorlist.add("Green");
      colorlist.add("Blue");
      colorlist.add("Gray");
      for (int i = 0; i < 20; i++)
        colorlist.add("Stub Entry " + i);
    }
    
    void draw() {
      background(currentColor);
    }
    
    void keyReleased() {
    }
    
    void mouseReleased() {
    
      if (mouseY>height/2)
        selectionlist = new SelectionKList(this, colorlist);
      else
        selectionlist = new SelectionKList(this, "Hello World", colorlist);
    }
    
    
    //===========================================================================
    // OTHER FUNCTIONS:
    
    void onSelectionKListSelection(SelectionKList klist)
    {
      String selection = klist.getSelection();
      if (selection == "Black")
        currentColor = color(0, 0, 0);
      else if (selection == "Red")
        currentColor = color(255, 0, 0);
      else if (selection == "Green")
        currentColor = color(0, 255, 0);
      else if (selection == "Blue")
        currentColor = color(0, 0, 255);
      else if (selection == "Gray")
        currentColor = color(128, 128, 128);
    }
    
    
    
    //===========================================================================
    // ANDROID ACTIVITY LIFECYCLE'S FUNCTIONS:
    
    
    
    //  @@@@@@@@@@@@
    @ Override 
      public void onResume() {
      super.onResume();
    
      act = this.getActivity();
      mC= act.getApplicationContext();
    
    }
    
    /**
     * 
     */
    
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    
    import processing.core.PApplet;
    import android.graphics.Color;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.ViewManager;
    import android.widget.AdapterView;
    import android.widget.ArrayAdapter;
    import android.widget.ListView;
    import android.widget.RelativeLayout;
    import android.widget.TextView;
    
    /**
     * The SelectionKList class provides an android UI scroll list. To receive the
     * selection data a sketch should define the following method:<br />
     * <br />
     * 
     * void onSelectionKListSelection(String selection) - selection is the string
     * selected from the list<br />
     */
    public class SelectionKList extends ListView {
    
      /** The parent. */
      private PApplet parent;
    
      /** The adapter. */
      public ArrayAdapter<String> adapter;
    
      /** The name. */
      String name = "SelectionKList";
    
      /** The selection. */
      String selection = "";
    
      /** The self. */
      ListView self;
    
      /** The layout. */
      RelativeLayout layout;
    
      /** The parent callback. */
      private Method parentCallback;
    
      /** The title. */
      String title = "";
    
      /**
       * Instantiates a new ketai list.
       *
       * @param _parent
       *            the _parent
       * @param data
       *            the data
       */
      public SelectionKList(PApplet _parent, ArrayList<String> data) {
        super(_parent.getActivity().getApplicationContext());
        parent = _parent;
        adapter = new ArrayAdapter<String>(parent.getActivity(), android.R.layout.simple_list_item_1, data);
        init();
      }
    
      /**
       * Instantiates a new ketai list.
       *
       * @param _parent
       *            the _parent
       * @param data
       *            the data
       */
      public SelectionKList(PApplet _parent, String[] data) {
        super(_parent.getActivity().getApplicationContext());
    
        parent = _parent;
        adapter = new ArrayAdapter<String>(parent.getActivity(), android.R.layout.simple_list_item_1, data);
        init();
      }
    
      /**
       * Instantiates a new ketai list.
       *
       * @param _parent
       *            the _parent
       * @param _title
       *            the _title
       * @param data
       *            the data
       */
      public SelectionKList(PApplet _parent, String _title, String[] data) {
        super(_parent.getActivity().getApplicationContext());
    
        parent = _parent;
        title = _title;
        adapter = new ArrayAdapter<String>(parent.getActivity(), android.R.layout.simple_list_item_1, data);
        init();
      }
    
      /**
       * Instantiates a new ketai list.
       *
       * @param _parent
       *            the _parent
       * @param _title
       *            the _title
       * @param data
       *            the data
       */
      public SelectionKList(PApplet _parent, String _title, ArrayList<String> data) {
        super(_parent.getActivity().getApplicationContext());
        parent = _parent;
        title = _title;
        adapter = new ArrayAdapter<String>(parent.getActivity(), android.R.layout.simple_list_item_1, data) {
          @Override
            public View getView(int position, View convertView, ViewGroup parent) {
            View view =super.getView(position, convertView, parent);
    
            TextView textView=(TextView) view.findViewById(android.R.id.text1);
    
            /**YOUR CHOICE OF COLOR*/
            textView.setTextColor(Color.BLUE);
    
            return view;
          }
        };
        init();
      }
    
      /**
       * Refresh.
       */
      public void refresh() {
        if (adapter == null)
          return;
        parent.getActivity().runOnUiThread(new Runnable() {
          public void run() {
            adapter.notifyDataSetChanged();
          }
        }
        );
      }
    
      /**
       * Gets the selection.
       *
       * @return the selection
       */
      public String getSelection() {
        return selection;
      }
    
      /**
       * Inits the.
       */
      public void init() {
        setBackgroundColor(Color.LTGRAY);
        setAlpha(1);
        self = this;
    
        layout = new RelativeLayout(parent.getActivity());
        SetTitleIfAny();
        setAdapter(adapter);
    
        setOnItemClickListener(new OnItemClickListener() {
          public void onItemClick(AdapterView<?> p, View view, int position, long id) {
    
            selection = adapter.getItem(int(id)).toString();
    
            layout.removeAllViewsInLayout();
            try {
              parentCallback.invoke(parent, new Object[] { self });
            } 
            catch (Exception ex) {
            }
    
            self.setVisibility(View.GONE);
            ((ViewManager) self.getParent()).removeView(self);
            parent.getActivity().runOnUiThread(new Runnable() {
              public void run() {
                layout.removeAllViews();
                layout.setVisibility(View.GONE);
              }
            }
            );
          }
        }
        );
    
        try {
          parentCallback = parent.getClass().getMethod("onSelectionKListSelection", new Class[] { SelectionKList.class });
          PApplet.println("Found onSelectionKListSelection...");
        } 
        catch (NoSuchMethodException e) {
        }
    
    
        addToMainView();
      }
    
      /**
       * Adds title if not empty
       */
      void SetTitleIfAny() {
        if (title != "") {
          TextView tv = new TextView(parent.getActivity());
          tv.setText(title);
          setHeaderDividersEnabled(true);
          addHeaderView(tv);
        }
      }
    
      /**
       * Add to the main view...
       */
      void addToMainView() {
        parent.getActivity().runOnUiThread(new Runnable() {
          @SuppressWarnings("deprecation")
            public void run() {
            parent.getActivity().addContentView(self, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, 
              ViewGroup.LayoutParams.FILL_PARENT));
          }
        }
        );
      }
    }
    
  • KetaiList

    Hi. I copied the KetaiList class into a new processing tab to be able to customize it. But I only managed to change the backGround color. I tried to set textColor and do some padding, but although it doesn't give any errors, it also hasn't any effect. Any idea what is wrong? Thanks in advance

    import java.lang.reflect.Method;
    import java.util.ArrayList; 
    import processing.core.PApplet;
    import android.graphics.Color;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.ViewManager;
    import android.widget.AdapterView;
    import android.widget.ArrayAdapter;
    import android.widget.ListView;
    import android.widget.RelativeLayout;
    import android.widget.TextView; 
    
    // void onKetaiListSelection(String selection) - selection is the string * selected from the list
    
    public class KetaiList extends ListView { 
    
      private PApplet parent; 
      private ArrayAdapter<String> adapter; 
      String name = "KetaiList"; 
      String selection = "";
      ListView self; 
      RelativeLayout layout; 
      private Method parentCallback; 
      String title = "";
      public KetaiList(PApplet _parent, ArrayList<String> data) {       
        super(_parent.getActivity().getApplicationContext());       
        parent = _parent;       
        adapter = new ArrayAdapter<String>(parent.getActivity(), android.R.layout.simple_list_item_1, data);        
        init();
      } 
      public KetaiList(PApplet _parent, String[] data) {        
        super(_parent.getActivity().getApplicationContext());       
        parent = _parent;       
        adapter = new ArrayAdapter<String>(parent.getActivity(), android.R.layout.simple_list_item_1, data);        
        init();
      }
      public KetaiList(PApplet _parent, String _title, String[] data) {     
        super(_parent.getActivity().getApplicationContext());       
        parent = _parent;       
        title = _title;     
        adapter = new ArrayAdapter<String>(parent.getActivity(), android.R.layout.simple_list_item_1, data);        
        init();
      } 
      public KetaiList(PApplet _parent, String _title, ArrayList<String> data) {        
        super(_parent.getActivity().getApplicationContext());       
        parent = _parent;       
        title = _title;     
        adapter = new ArrayAdapter<String>(parent.getActivity(), android.R.layout.simple_list_item_1, data);        
        init();
      } 
      public void refresh() {       
        if (adapter == null)            return;     
        parent.getActivity().runOnUiThread(new Runnable() {         
          public void run() {               
            adapter.notifyDataSetChanged();
          }
        }
        );
      } 
      public String getSelection() {        
        return selection;
      }
      private void init() {     
        setBackgroundColor(Color.BLUE);     
      //  setTextColor(Color.BLACK);
        setAlpha(1);        
        self = this;        
        layout = new RelativeLayout(parent.getActivity());      
    
        if (title != "") {          
          TextView tv = new TextView(parent.getActivity());
       //   tv.setPadding(100,100,0,0);
          tv.setText(title);            
       //   tv.setTextColor(Color.parseColor("#bdbdbd"));
          setHeaderDividersEnabled(true);           
          addHeaderView(tv);
        }       
        try {           
          parentCallback = parent.getClass().getMethod("onKetaiListSelection", new Class[] { KetaiList.class });            
          PApplet.println("Found onKetaiListSelection...");
        } 
        catch (NoSuchMethodException e) {
        }       
        setAdapter(adapter);        
        setOnItemClickListener(new OnItemClickListener() {          
          public void onItemClick(AdapterView<?> p, View view, int position, long id) {                 
            selection = adapter.getItem(position).toString();               
            layout.removeAllViewsInLayout();                
            try {                   
              parentCallback.invoke(parent, new Object[] { self });
            } 
            catch (Exception ex) {
            }               
            self.setVisibility(View.GONE);              
            ((ViewManager) self.getParent()).removeView(self);              
            parent.getActivity().runOnUiThread(new Runnable() {                 
              public void run() {                       
                layout.removeAllViews();                        
                layout.setVisibility(View.GONE);
              }
            }
            );
          }
        }
        ); 
        parent.getActivity().runOnUiThread(new Runnable() {         
          @ SuppressWarnings("deprecation")     
            public void run() {             
            parent.getActivity().addContentView(self, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
          }
        }
        );
      }
    }
    
  • tint() PImage Android Mode

    @noel I need permission to access your image. Make it available through other means plz.

    In the meantime, I tested both JAVA2D and P2D and the tint works. I used two images

    https://www.svgimages.com/james-dean-rebel-stencil.html
    https://www.svgimages.com/horse-stand.html

    Kf

    //REFERENCES: https://forum.processing.org/two/discussion/26691/tint-pimage-android-mode#latest
    
    //INSTRUCTIONS:
    //         *-- Tap upper half of sketch to reset and start tint effect
    //         *-- Tap lower half of sketch to switch images
    //         *--
    //         *--
    
    //===========================================================================
    // IMPORTS:
    
    import android.app.Activity;
    import android.content.Context;
    import android.widget.FrameLayout;
    //import android.app.Fragment;
    
    import android.os.Environment;
    import android.graphics.Color;
    import android.widget.Toast;
    import android.os.Looper;
    import android.view.WindowManager;
    import android.os.Bundle;
    import android.view.ViewParent;
    import android.view.ViewGroup;
    import android.view.View;
    import android.widget.RelativeLayout;
    import android.view.LayoutInflater;
    import android.R.string;
    
    
    
    //===========================================================================
    // FINAL FIELDS:
    
    
    final String FN1="horse-stand-512x512.png";
    final String FN2="james-dean-rebel-stencil-256x256.png";
    
    // https://github.com/processing/processing-android/blob/master/core/src/processing/core/PConstants.java#L47
    //final String RENDERER_DEF=JAVA2D;
    final String RENDERER_DEF=P2D;
    
    //===========================================================================
    // GLOBAL VARIABLES:
    
    Activity act;
    Context mC;
    
    int tintCtr = 255;
    boolean flag1;
    PImage img;
    int cimg;
    
    //===========================================================================
    // PROCESSING DEFAULT FUNCTIONS:
    
    void setup() {
      size (600, 600,RENDERER_DEF);
      orientation(PORTRAIT);
    
      background(255);
      cimg=0;
      LoadImageNow();
      tint(255, tintCtr); 
      image(img, 0, 0);
    
    
      act = this.getActivity();
      Looper.prepare();
    
      textAlign(CENTER, CENTER);
      rectMode(CENTER);
    
      fill(255);
      noStroke();
      textSize(14);
    }
    
    void draw() {  
      background(255);
      tint(255, tintCtr); 
      image(img, 0, 0);
    
      if (flag1) {
        if (frameCount%15==0) {
          tintCtr -= 6;     
        }
    
        if (tintCtr < 40) 
          flag1 = false;
      } 
    
      fill(250, 155, 20, 100);
      rect(width>>1, height*0.95, 3*width>>2, height*0.1);
      fill(0);
      if (flag1)
        text("Current tint "+tintCtr, width>>2, height*0.95);
      else
        text("Tap upper half to restart\n@"+RENDERER_DEF, width>>1, height*0.95);
    }
    
    void mouseReleased() {
    
      if (mouseY<height>>1) {
        flag1 = !flag1;
    
        if (flag1) tintCtr=255;
      } else {
        cimg=(cimg+1)%2;
        LoadImageNow();
      }
    }
    
    //Assumes cimg is properly set and within range
    void LoadImageNow() {
      if (cimg==0)
        img = loadImage(FN1);
      else
        img = loadImage(FN2);
    
      img.resize(int(width*0.75), 0);
      flag1=false;
      tintCtr=255;
    }
    
    
    //===========================================================================
    // OTHER FUNCTIONS: