2

What i am trying to achieve is to draw dot at the exact same location as black dot already present in image , but there are problem that i have to face regarding image:

  1. Image can change its densities in multiple screens(so no fixed size)
  2. Given image can be of any size , i have to convert it to appropriate size to show on custom View.
  3. and How to show image in custom view so its density remain the same ?

Now problems regarding dots drawing:

  1. How can i identify black dots x,y axis dynamically to draw at the same exact black dot drawn in image of custom view.
  2. Is there a good way to achieve question 1 dynamically or i should hard code dots.

What i have done so far:

  1. I have moved all images to drawable folder and done layout_width = wrap_content and height the same as width.

    <com.jutt.dotbot.ConnectDotsView
    android:id="@+id/gfxImage"
    android:layout_width="500dpi"
    android:layout_height="600dpi"
    android:layout_marginTop="100dip"
    android:layout_centerHorizontal="true"/>
    
  2. I've look hard coded points by Toast the point on each ACTION_DOWN in onTouchEvent and then noted then and given to the class ConnectDotsView .

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        touch_start(x, y);
        invalidate();
        L.s(getContext(), "x = "+x+"y = "+y);
        break;
    
  3. After i've noted all points drawn , i am giving this class back that same points to draw , by calling:

    public void setPoints(List<Point> points) {
        this.mPoints = points;
    }
    
  4. Now Biggest problem [which i think still persist] , (x,y) on screen 1152w*720h may not be same on 480w*600h , so what i've done is who a function to actually convert those points.

    private static final int OLDSCREENX = 1152;
    private static final int OLDSCREENY = 720;
    
    private int[] makeDimentionGeneric(float oldScreenX, float oldScreenY,
            float oldX, float oldY) {
        // get screen size
        DisplayMetrics displaymetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        final float y = displaymetrics.heightPixels;
        final float x = displaymetrics.widthPixels;
        int[] i = new int[] { (int) ((oldX / oldScreenX) * x),
                (int) ((oldY / oldScreenY) * y) };
        return i;
    }
    

and i am calling this while setting the points like makeDimentionGeneric(OLDSCREENX, OLDSCREENY, p.x, p.y); when p.x and p.y are hardcoded stored value from screen.

Now what happens when i try to run it in different devices.

Right side is emulator and left is bluestack

When am i doing it wrong and how can i achieve it correctly ? please guys i've worked hard studied but can't seems to find a better approach than i've mentioned.

[Update] as requested(21 jul 2015):

private int[] makeDimentionGeneric(float oldScreenX, float oldScreenY,
        float oldX, float oldY) {
    // convert all px to dp
    oldScreenY = convertPixelsToDp(oldScreenY, this);
    oldScreenX = convertPixelsToDp(oldScreenX,this);
    oldX = convertPixelsToDp(oldX,this);
    oldY = convertPixelsToDp(oldY,this);

    // get screen size
    DisplayMetrics displaymetrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
    final float y = convertPixelsToDp(displaymetrics.heightPixels, this);
    final float x = convertPixelsToDp(displaymetrics.widthPixels, this);

    int[] i = new int[] { (int)((oldX / oldScreenX) * x),
            (int) ((oldY / oldScreenY) * y) };

    return i;

}
Zulqurnain Jutt
  • 298
  • 3
  • 20
  • change your convention to draw dot x/y - in px of original screen -> dp -> pixels on your current screen. – JohanShogun Jul 21 '15 at 21:21
  • are you saying i should draw in px instead of dp ? – Zulqurnain Jutt Jul 21 '15 at 21:25
  • No, but your dot locations should be in dp. From the pictures it looks like your conversion is wrong :) – JohanShogun Jul 21 '15 at 21:28
  • @JohanShogun i also think that, problem is somewhere with conversion and screen sizes , i have asked a separate question on that , can you plz answer [this](http://stackoverflow.com/questions/31548891/how-to-get-width-and-height-of-resized-custom-view-before-it-is-drawn) – Zulqurnain Jutt Jul 21 '15 at 21:35

1 Answers1

1

Since your image differs depending on DPI your pixel calculations must also differ depending on DPI. Consider the following question:

Converting pixels to dp

In your case (copied from answer in above question) you probably want to use this method:

/**
 * This method converts device specific pixels to density independent pixels.
 *
 * @param px A value in px (pixels) unit. Which we need to convert into db
 * @param context Context to get resources and device specific display metrics
 * @return A float value to represent dp equivalent to px value
 */
public static float convertPixelsToDp(float px, Context context){
    Resources resources = context.getResources();
    DisplayMetrics metrics = resources.getDisplayMetrics();
    float dp = px / (metrics.densityDpi / 160f);
    return dp;
}
Community
  • 1
  • 1
JohanShogun
  • 2,956
  • 21
  • 30
  • If you're given the pixels for lets say xhdpi screen and you want to use them on a mdpi screen, then you'd be best served by simply converting the pixels to DP (xhdpi pixel -> dp) and then converting it back to pixels for your screen (dp -> mdpi pixel). It may be a good idea to store them as DP instead of pixels though. – JohanShogun Jul 21 '15 at 12:24
  • do you suggest to convert all hard coded points to dp for storing ? – Zulqurnain Jutt Jul 21 '15 at 12:25
  • I think you'd be best served by storing your hard coded points as DP instead of PX and then set them up once per device once you know its dpi. – JohanShogun Jul 21 '15 at 12:27
  • No , i've tested it , with same values converting them as dp from px , but still some of them are dispersing. – Zulqurnain Jutt Jul 21 '15 at 12:43