Cómo reposicionar puntos en una vista en la resolución de pantalla diferente?

Tengo el conjunto de puntos dibujados en una vista como se muestra en la imagen de abajo.

Detalles:

Tengo una matriz de coordenadas xey. Pero el problema es que no se ajusta de acuerdo a diferentes resoluciones de pantalla.

Lo que quiero:

Quiero que esté en el centro de la vista independientemente de la resolución de la pantalla.

Aquí está mi código:

public class FirstFragment extends Fragment implements Step { int[] y = {381, 379, 372, 351, 329, 305, 269, 230, 195, 156, 117, 95, 64, 44, 24, 15, 13, 25, 46, 72, 107, 128, 162, 195, 222, 244, 266, 298, 324, 341, 363, 372, 378, 376, 363, 339, 308, 281, 263, 246, 237, 235, 244, 259, 274, 298, 318, 334, 353, 383, 414, 443, 467, 490, 512, 538, 562, 582, 596, 604, 602, 586, 562, 532, 510, 485, 461, 439, 414, 391, 365, 344, 322, 305, 262, 246, 235, 234, 241, 257, 279, 306, 335, 359, 375, 381}; int[] x = {93, 109, 130, 157, 181, 207, 253, 297, 336, 380, 406, 413, 415, 405, 381, 358, 326, 296, 272, 261, 266, 274, 301, 336, 368, 397, 423, 461, 487, 508, 540, 562, 587, 613, 639, 658, 666, 659, 647, 629, 607, 583, 559, 527, 496, 461, 444, 425, 406, 375, 339, 313, 292, 274, 263, 261, 269, 284, 304, 332, 360, 395, 413, 421, 418, 403, 382, 360, 339, 304, 276, 253, 229, 207, 164, 136, 105, 79, 53, 31, 18, 13, 19, 35, 58, 93}; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.first_fragment, container, false); } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); final ConnectDotsView connectDotsView = (ConnectDotsView) view.findViewById(R.id.connect_dots_view); connectDotsView.setOnCompleteListener(new ConnectDotsView.CompleteListener() { @Override public void onCompleteListener() { Toast.makeText(getActivity(), "Completed", Toast.LENGTH_SHORT).show(); Log.e("Done", "true"); } }); connectDotsView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { Rect rect = new Rect(); connectDotsView.getLocalVisibleRect(rect); Log.e("Width", rect.width() + ""); Log.e("Height", rect.height() + ""); Log.e("left", rect.left + ""); Log.e("right", rect.right + ""); Log.e("top", rect.top + ""); Log.e("bottom", rect.bottom + ""); int scale = (int) getResources().getDisplayMetrics().density; List<Point> points = new ArrayList<>(); for (int i = 0, j = 0; i < x.length && j < y.length; i++, j++) { Point p = new Point(x[i] / scale + rect.left, y[j] / scale + rect.top); points.add(p); } connectDotsView.setPoints(points); } }); } @Override public VerificationError verifyStep() { return null; } @Override public void onSelected() { } @Override public void onError(@NonNull VerificationError error) { } } 

Clase de vista personalizada:

 package com.sagar.quizdemo; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Point; import android.util.AttributeSet; import android.util.TypedValue; import android.view.MotionEvent; import android.view.View; import java.util.ArrayList; import java.util.List; /** * Displaying canvas with optional dots drawn on it. User can connect dots with * straight lines. First dot can be connected with second dot, second with third * etc. * * @author lecho */ public class ConnectDotsView extends View { private Bitmap mBitmap; private Canvas mCanvas; private Path mPath; private Paint mPaint; private static final int TOUCH_TOLERANCE_DP = 24; private static final int BACKGROUND = 0xFFDDDDDD; // Points to be connected. private List<Point> mPoints = new ArrayList<>(); private int mLastPointIndex = 0; private int mTouchTolerance; private boolean isPathStarted = false; CompleteListener completeListener; public ConnectDotsView(Context context) { super(context); mCanvas = new Canvas(); mPath = new Path(); initPaint(); } interface CompleteListener { void onCompleteListener(); } public void setOnCompleteListener(CompleteListener listener) { completeListener = listener; } public ConnectDotsView(Context context, AttributeSet attrs) { super(context, attrs); mCanvas = new Canvas(); mPath = new Path(); initPaint(); } public ConnectDotsView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mCanvas = new Canvas(); mPath = new Path(); initPaint(); } public void clear() { mBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); mBitmap.eraseColor(BACKGROUND); mCanvas.setBitmap(mBitmap); invalidate(); } @Override protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) { super.onSizeChanged(width, height, oldWidth, oldHeight); clear(); } @Override protected void onDraw(Canvas canvas) { canvas.drawColor(BACKGROUND); canvas.drawBitmap(mBitmap, 0, 0, null); canvas.drawPath(mPath, mPaint); // TODO remove if you don't want points to be visible. for (Point point : mPoints) { canvas.drawPoint(point.x, point.y, mPaint); } } @Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: touch_start(x, y); invalidate(); break; case MotionEvent.ACTION_MOVE: touch_move(x, y); invalidate(); break; case MotionEvent.ACTION_UP: touch_up(x, y); invalidate(); break; } return true; } private void touch_start(float x, float y) { if (checkPoint(x, y, mLastPointIndex)) { mPath.reset(); // User starts from given point so path can be drawn. isPathStarted = true; } else { // User starts move from point which does not belong to mPoints list isPathStarted = false; } } private void touch_move(float x, float y) { if (isPathStarted) { mPath.reset(); Point point = mPoints.get(mLastPointIndex); mPath.moveTo(point.x, point.y); if (checkPoint(x, y, mLastPointIndex + 1)) { point = mPoints.get(mLastPointIndex + 1); mPath.lineTo(point.x, point.y); mCanvas.drawPath(mPath, mPaint); mPath.reset(); ++mLastPointIndex; } else { int positionIndex = mLastPointIndex + 1; if (positionIndex >= mPoints.size()) { completeListener.onCompleteListener(); } else { mPath.lineTo(x, y); } } } } private void touch_up(float x, float y) { mPath.reset(); if (checkPoint(x, y, mLastPointIndex + 1) && isPathStarted) { // Move finished at valid point so I draw whole line. // That's the start point of current line segment. Point point = mPoints.get(mLastPointIndex); mPath.moveTo(point.x, point.y); // And that's the end point. point = mPoints.get(mLastPointIndex + 1); mPath.lineTo(point.x, point.y); mCanvas.drawPath(mPath, mPaint); mPath.reset(); // Increment point index. ++mLastPointIndex; isPathStarted = false; } } /** * Checks if user touch point with some tolerance */ private boolean checkPoint(float x, float y, int pointIndex) { if (pointIndex >= mPoints.size()) { // All dots already connected. return false; } Point point = mPoints.get(pointIndex); if (x > (point.x - mTouchTolerance) && x < (point.x + mTouchTolerance)) { if (y > (point.y - mTouchTolerance) && y < (point.y + mTouchTolerance)) { return true; } } return false; } /** * Sets up paint attributes. */ private void initPaint() { mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setDither(true); mPaint.setColor(Color.BLACK); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setStrokeWidth(12); mTouchTolerance = dp2px(TOUCH_TOLERANCE_DP); } /** * Converts dpi units to px * * @param dp * @return */ private int dp2px(int dp) { Resources r = getContext().getResources(); float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics()); return (int) px; } public void setPaint(Paint paint) { this.mPaint = paint; } public Bitmap getBitmap() { return mBitmap; } public List<Point> getPoints() { return mPoints; } public void setPoints(List<Point> points) { this.mPoints = points; } } 

Enlace de la imagen : /images//n67mq.png

Porfavor ayudame a resolver este problema.

Puede dibujar en el centro utilizando los siguientes cálculos,

 connectDotsView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { Rect rect = new Rect(); // Fist find the min and max value for x axis int minX = x[0]; int maxX = x[0]; for (int i = 1; i <= x.length - 1; i++) { if (maxX < x[i]) { maxX = x[i]; } if (minX > x[i]) { minX = x[i]; } } // Find min and max vlaue for Y axis int minY = y[0]; int maxY = y[0]; for (int i = 1; i <= y.length - 1; i++) { if (maxY < y[i]) { maxY = y[i]; } if (minY > y[i]) { minY = y[i]; } } connectDotsView.getLocalVisibleRect(rect); Log.e("Width", rect.width() + ""); Log.e("Height", rect.height() + ""); Log.e("left", rect.left + ""); Log.e("right", rect.right + ""); Log.e("top", rect.top + ""); Log.e("bottom", rect.bottom + ""); // Find the scale factor based on the view you allocated in the screen float scaleX = ((float) ((float) rect.width() / (float) maxX)); float scaleY = ((float) ((float) rect.height() / (float) maxY)); final float scale; // Take the lowest scale factor if (scaleX > scaleY) { scale = scaleY; } else { scale = scaleX; } // find the left and top int left = (rect.width() - ((int) ((float) maxX * scale)) - ((int) ((float) minX * scale))) / 2; int top = (rect.height() - ((int) ((float) maxY * scale)) - ((int) ((float) minY * scale))) / 2; // base on the above calculation draw in a view List<Point> points = new ArrayList<>(); for (int i = 0, j = 0; i < x.length && j < y.length; i++, j++) { Point p = new Point(((int) ((float) x[i] * scale)) + left, (int) ((float) y[j] * scale) + top); points.add(p); } connectDotsView.setPoints(points); } }); 

La salida será así,

Introduzca aquí la descripción de la imagen

  • Cómo obtener Bitmap de WebView genera un fallo de OutOfMemory
  • Android - Lienzo drawLine dentro de ImageView
  • Cómo obtener el rectángulo inscrito en un clip de lienzo
  • Imagen en lienzo a archivo JPEG
  • Dibuja un círculo en el centro de la lona
  • Cómo dibujar un camino en un lienzo de Android con la animación?
  • Cómo rellenar rectángulo con opacidad en android
  • Solo toque en ANDROID
  • Animar dibujo de círculo / arco sobre lienzo
  • Visualización de texto de desplazamiento en forma de carpintería en Android
  • Programación de Android: ¿Cómo dibujar texto multilínea en un rectángulo?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.