Vista personalizada drawArc, detecta el tacto del usuario en la trayectoria de trazado del arco
Estoy creando una vista personalizada que es una especie de vista de progreso de arco deslizante. Puedo dibujar más o menos del arco basado en donde el usuario toca (en el eje x) calculando el barrido, lo hago calculando primero el percept Donde el usuario tocó a lo largo del eje x..0% sería todo el camino a la izquierda y el 100% sería todo el camino a la derecha.
Quiero llevar esto un paso más allá, en lugar de dibujar el arco basado en la coordenada x que el usuario presiona, quiero hacer que se mueva sólo cuando el usuario toca el camino de trazado de arco real, por lo que es más realista. Todavía soy nuevo a las vistas de encargo y mi matemáticas es limitado pero si consigo algunos extremidades agradecería agradecido
- Cómo saber si Proguard ha hecho su trabajo
- ¿Pasar un argumento al llamar a setOnClickListener?
- Java.lang.NullPointerException en android.support.v7.widget.RecyclerView.onMeasure
- Configuración de la orientación de la pantalla Actividad de Android con values.xml
- Conexión larga de sondeo TCP de Android
class ArcProgress extends View { Context cx; float width; float height; float center_x, center_y; final RectF oval = new RectF(); final RectF touchArea = new RectF(); float sweep = 0; float left, right; int percent = 0; public ArcProgress(Context context) { super(context); cx = context; } public int getPercentage() { return percent; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); setBackgroundColor(0xfff0ebde); width = (float) getWidth(); height = (float) getHeight(); float radius; if (width > height) { radius = height / 3; } else { radius = width / 3; } Paint paint = new Paint(); paint.setAntiAlias(true); paint.setColor(0xffd2c8b6); paint.setStrokeWidth(35); paint.setStyle(Paint.Style.STROKE); center_x = width / 2; center_y = height / 2; left = center_x - radius; float top = center_y - radius; right = center_x + radius; float bottom = center_y + radius; oval.set(left, top, right, bottom); //this is the background arc, it remains constant canvas.drawArc(oval, 180, 180, false, paint); paint.setStrokeWidth(10); paint.setColor(0xffe0524d); //this is the red arc whichhas its sweep argument manipulated by on touch canvas.drawArc(oval, 180, sweep, false, paint); } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_MOVE) { float xPosition = event.getX(); float yPosition = event.getY(); if (oval.contains(xPosition, yPosition)) { float x = xPosition - left; float s = x * 100; float b = s / oval.width(); percent = Math.round(b); sweep = (180 / 100.0f) * (float) percent; invalidate(); } else { if (xPosition < left) { percent = 0; sweep = (180 / 100.0f) * (float) percent; invalidate(); } if (xPosition > right) { percent = 100; sweep = (180 / 100.0f) * (float) percent; invalidate(); } } } return true; } }
- Perder los extras de Intent cuando regresa a Actividad
- Ningún archivo project.properties y NullPointerException durante la creación de la nueva aplicación android
- Error al iniciar Android Studio: Error al crear JVM: código de error-6
- Android N cambia el idioma mediante programación
- Cómo insertar programaticamente entradas de registro de llamadas con nombre de presentación y foto?
- Conexión de Https con conexión cerrada por peer en Android 6.0
- PreferenciaActividad con varios archivos de preferencias
- Convertir lista a matriz en Java
¿Esto funciona para tí? No necesitas un montón de matemáticas. Puede calcular la distancia del punto de contacto desde el centro de su arco (es un círculo por lo que es fácil) y compararlo con el radio que está utilizando. Eso le dirá si el punto está en el arco (casi, ver abajo para el caso completo).
Point touchEv = ...; Point circleCenter = ...; //the radius of the circle you used to draw the arc float circleRadius = ...; //how far from the arc should a touch point treated as it's on the arc float maxDiff = getResources().getDimension(R.dimen.max_diff_dp); //calculate the distance of the touch point from the center of your circle float dist = Math.pow(touchEv.x-circleCenter.x,2) + Math.pow(touchEv.y- circleCenter.y,2) dist = Math.sqrt(dist); //We also need the bounding rect of the top half of the circle (the visible arc) Rect topBoundingRect = new Rect(circleCenter.x - circleRadius, circleCenter.y - circleRadius, circleCenter.x + circleRadius, circleCenter.y); if (Math.abs(dist - circleRadius) <= maxDiff && topBoundingRect.contains(touchEv.x, touchEv.y)) { // the user is touching the arc }
Quiero hacer que se mueva sólo cuando el usuario toca la trayectoria de trazado de arco real
Al principio de onTouchEvent()
debe comprobar si xPosition
y yPosition
cumplen alguna condición. Si es así, usted hace las cosas, que está haciendo ahora. Si no, return true
.
Condición:
Queremos comprobar si x, y están en ese fondo de arco gris:
Calculemos una distancia de (x, y) a ese punto (a, b) en el centro:
final dist = distance(x, y, a, b)
distance()
es una distancia euclídea simple entre los puntos (x, y) y (a, b):
double distance(int x, int y, int a, int b) { return Math.sqrt((x - a) * (x - a) + (y - b) * (y - b)); }
X, y están en ese fondo de arco gris, si y > Y && dist >= r && dist <= R
- Por qué EditText no se está expandiendo a fill_parent
- Uso de adb con varios dispositivos con el mismo número de serie