2

I know that I have to much going on in my main thread but I'm looking for a work-around.

Here is my app's structure:

Currently I have my main activity, which has 6 clickable imageviews (that open new activities), the problem happens when one of the activities are opened. In this activity I'm using a SlidingTabLayout with 3 tabs.

This is what I am trying to achieve:

I'm creating a piano out of drawables(shapes)

For example, this is the black key:

<shape
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:shape="rectangle">
<stroke
    android:width="1dp"
    android:color="#FF000000" />

    <solid 
      android:color="#FF000000"/>
</shape> 

Then I call this drawables in my layout to create the piano:

<ImageView
    android:layout_width="8dp"
    android:layout_height="37dp"
    android:layout_marginLeft="40dp"
    android:layout_marginStart="10.5dp"
    android:src="@drawable/key_black" />

I'm displaying 7 Imageviews for the black keys and 10 Imageviews for the white keys PER piano and I have 11 pianos PER tab. So that is 187 Imageview per tab.

So I understand that this will be harsh on my CPU. I'm looking for a way to do this of my main thread? To do it in the background? To do it without experiencing lagging?

HB.
  • 4,116
  • 4
  • 29
  • 53
  • Can you provide an Image of what it should look like and explain what you want to achive/ what it should do? Apparently you want the user to interact with the keys of the piano? But 187 interactable items seem a little much to have on one screen – AljoSt Jul 07 '16 at 06:12
  • I just want to display the piano's, i don't want the user to interact with it. – HB. Jul 07 '16 at 06:24
  • Possible duplicate of [The application may be doing too much work on its main thread](http://stackoverflow.com/questions/14678593/the-application-may-be-doing-too-much-work-on-its-main-thread) – Janki Gadhiya Jul 07 '16 at 06:29
  • Why do you need the keys to be in individual imageviews then? How about creating the piano as a whole in a .png or by using Android shapes and then put it in one imageView? Or should it animate? – AljoSt Jul 07 '16 at 06:30
  • Every piano show different keys that are pressed, so every piano looks different, so using one png of a piano won't work. Using multiple png's for each piano will cause the same problem. – HB. Jul 07 '16 at 06:37
  • If you could provide an image of how it should look, it would be easier to help. Anyway, if you just need an image for each different piano, I would create a base image (all keys not pressed) and then draw the selected keys onto it via a [Canvas](https://developer.android.com/reference/android/graphics/Canvas.html). Depends of course how those pressed Keys should look – AljoSt Jul 07 '16 at 06:52
  • here is a link to a image of what I want to achieve: https://postimg.org/image/ow7zxwswn/ – HB. Jul 07 '16 at 07:20

1 Answers1

0

So as mentioned above, I would create a base image for the piano, and adjust it according to the currently pressed keys. The code below shows the general idea: Load the base image from R.drawable, use the indices for the pressed keys, as well as the size of the image to create Paths, draw the Paths, return the image. If you need clearification, let me know.

public Bitmap getPianoImage(Context context, int[] pressedKeyIndices){
    Bitmap pianoImage = BitmapFactory.decodeResource(context.getResources(), R.drawable.pianoBase);
    Canvas canvas = new Canvas(pianoImage);
    Paint paint = new Paint();
    paint.setColor(Color.RED);
    paint.setStyle(Paint.Style.FILL);

    for(int pressedKeyIndex : pressedKeyIndices){
        Path path = getPathForKeyIndex(pressedKeyIndex, pianoImage.getWidth(), pianoImage.getHeight());
        canvas.drawPath(path, paint);
    }

    return pianoImage;
}

private Path getPathForKeyIndex(int idx, int w, int h){

    Path path = new Path();

    switch(idx){
        case 0:
            path.moveTo(0f*w, 0f*h); // used for first point
            path.lineTo(0f*w, 1f*h);
            path.lineTo(0.1f*w, 1f*h);
            path.lineTo(0.1f*w, 0.5f*h);
            path.lineTo(0.08f*w, 0.5f*h);
            path.lineTo(0.08f*w, 0f*h);
            path.lineTo(0f*w, 0f*h);
            break;
        case 1: ...
    }

    return path;
}
AljoSt
  • 439
  • 4
  • 19
  • Could you please clarify what I should do in my xml? – HB. Jul 07 '16 at 08:34
  • You don't need any xml file. Put the base image of the piano (only black and white) in the `R.drawable` folder (-> `R.drawable.pianoBase`). And then use the code above (that needs to be completed) to create a Bitmap. The Bitmap takes the base image and colors the areas that correspond to ne indecies that you pass in as an argument of the function. – AljoSt Jul 07 '16 at 09:16
  • I've placed the image in R.drawable and I've pasted your code in but nothing happens, can't see the image.. I understand what you are saying but I cant see the image – HB. Jul 07 '16 at 09:26
  • Well first of all, the code above needs to be completed. You need to specify a path for each of the 17 keys in the `getPathForKeyIndex(int idx, int w, int h)` function. The path needs to trace the outline of each key in the image. Then, if you want to display an image with keys 1 and 4 pressed (for example), you pass those as an Array to the `getPianoImage(Context context, int[] pressedKeyIndices)` function. The function returns the Bitmap that you can display then – AljoSt Jul 07 '16 at 09:34
  • Ok I got it working. I duplicated it to test if there is a improvement in performance and there is still no improvement. – HB. Jul 07 '16 at 09:46
  • Can you please edit your current code into your intial post? Please show the complete code (that is relevant) for creating the fragment – AljoSt Jul 07 '16 at 09:57