2011-07-23 8 views
8

tengo dos ImageButtons, cada uno dentro de un RelativeLayout y estos dos RelativeLayouts están en otro Relative Lay, quiero establecer TouchDelegate para cada ImageButton. Si normalmente agrego TouchDelegate a cada ImageButton y su pariente RelativeLayout, solo un ImageButton funciona correctamente, otro no extiende su área de clic. Así que, por favor, ayúdenme sobre cómo usar TouchDelegate en ambos ImageButtons. Si no es posible, ¿cuál puede ser una forma efectiva de extender el área de clic de una vista? Gracias de antemano ........Cómo usar Multiple TouchDelegate

Aquí está mi código XML:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout android:id="@+id/FrameContainer" 
android:layout_width="fill_parent" android:layout_height="fill_parent" 
xmlns:android="http://schemas.android.com/apk/res/android"> 
<RelativeLayout android:layout_alignParentLeft="true" 
    android:id="@+id/relativeLayout3" android:layout_width="wrap_content" 
    android:layout_height="wrap_content"> 
    <RelativeLayout android:layout_alignParentLeft="true" 
     android:id="@+id/relativeLayout1" android:layout_width="113dip" 
     android:layout_height="25dip"> 
     <ImageButton android:id="@+id/tutorial1" 
      android:layout_width="wrap_content" android:layout_height="wrap_content" 
      android:background="@null" android:src="@drawable/tutorial" /> 
    </RelativeLayout> 
    <RelativeLayout android:layout_alignParentLeft="true" 
     android:id="@+id/relativeLayout2" android:layout_width="113dip" 
     android:layout_height="25dip" android:layout_marginLeft="100dip"> 
     <ImageButton android:id="@+id/tutorial2" 
      android:layout_width="wrap_content" android:layout_height="wrap_content" 
      android:background="@null" android:src="@drawable/tutorial" 
      android:layout_marginLeft="50dip" /> 
    </RelativeLayout> 
</RelativeLayout> 

Mi Clase de actividad:

import android.app.Activity; 
import android.graphics.Rect; 
import android.os.Bundle; 
import android.view.TouchDelegate; 
import android.view.View; 
import android.widget.ImageButton; 
import android.widget.Toast; 

public class TestTouchDelegate extends Activity { 
/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    View mParent1 = findViewById(R.id.relativeLayout1); 
    mParent1.post(new Runnable() { 
     @Override 
     public void run() { 
      Rect bounds1 = new Rect(); 
      ImageButton mTutorialButton1 = (ImageButton) findViewById(R.id.tutorial1); 
      mTutorialButton1.setEnabled(true); 
      mTutorialButton1.setOnClickListener(new View.OnClickListener() { 
       public void onClick(View view) { 
        Toast.makeText(TestTouchDelegate.this, "Test TouchDelegate 1", Toast.LENGTH_SHORT).show(); 
       } 
      }); 

      mTutorialButton1.getHitRect(bounds1); 
      bounds1.right += 50; 
      TouchDelegate touchDelegate1 = new TouchDelegate(bounds1, mTutorialButton1); 

      if (View.class.isInstance(mTutorialButton1.getParent())) { 
       ((View) mTutorialButton1.getParent()).setTouchDelegate(touchDelegate1); 
      } 
     } 
    }); 

    //View mParent = findViewById(R.id.FrameContainer); 
    View mParent2 = findViewById(R.id.relativeLayout2); 
    mParent2.post(new Runnable() { 
     @Override 
     public void run() { 
      Rect bounds2 = new Rect(); 
      ImageButton mTutorialButton2 = (ImageButton) findViewById(R.id.tutorial2); 
      mTutorialButton2.setEnabled(true); 
      mTutorialButton2.setOnClickListener(new View.OnClickListener() { 
       public void onClick(View view) { 
        Toast.makeText(TestTouchDelegate.this, "Test TouchDelegate 2", Toast.LENGTH_SHORT).show(); 
       } 
      }); 

      mTutorialButton2.getHitRect(bounds2); 
      bounds2.left += 50; 
      TouchDelegate touchDelegate2 = new TouchDelegate(bounds2, mTutorialButton2); 

      if (View.class.isInstance(mTutorialButton2.getParent())) { 
       ((View) mTutorialButton2.getParent()).setTouchDelegate(touchDelegate2); 
      } 
     } 
    }); 

} 

}

Respuesta

3

Hay solo se supone que es un delegado de un toque para cada vista. La documentación para getTouchDelegate() en la clase de vista se lee:

"Obtiene el TouchDelegate para esta vista".

Solo debe haber un TouchDelegate. Para usar solo un TouchDelegate por vista, puede ajustar cada vista tangible dentro de una vista con dimensiones que reflejen lo que le gustaría que fuera tangible. Un desarrollador de Android a la plaza da un ejemplo de cómo se puede hacer esto por (http://www.youtube.com/watch?v=jF6Ad4GYjRU & t = 37m4s) Vistas múltiples utilizando sólo un método estático:

public static void expandTouchArea(final View bigView, final View smallView, final int extraPadding) { 
bigView.post(new Runnable() { 
    @Override 
    public void run() { 
     Rect rect = new Rect(); 
     smallView.getHitRect(rect); 
     rect.top -= extraPadding; 
     rect.left -= extraPadding; 
     rect.right += extraPadding; 
     rect.bottom += extraPadding; 
     bigView.setTouchDelegate(new TouchDelegate(rect, smallView)); 
    } 
}); 

}

Digamos que no quiere saturar su jerarquía de vista. Hay otras dos opciones en las que puedo pensar. Puede definir los límites de lo que se puede tocar dentro de la vista táctil y asegurarse de pasar todos los touchevents a esa vista secundaria de las vistas padre respectivas. O puede anular getHitRect() para la vista táctil. Lo primero agilizará rápidamente su código y lo hará difícil de entender, por lo que este último es el mejor camino a seguir. Usted quiere ir con la anulación de getHitRect.

Dónde mPadding es la cantidad de área adicional que desea ser palpable alrededor de su punto de vista, se podría utilizar algo como lo siguiente:

@Override 
public void getHitRect(Rect outRect) { 
    outRect.set(getLeft() - mPadding, getTop() - mPadding, getRight() + mPadding, getTop() + mPadding); 
} 

Si utiliza un código como el anterior se tendrá que considerar qué vistas tangibles están cerca. El área táctil de la Vista que está más alta en la pila podría superponerse sobre otra Vista.

Otra opción similar sería cambiar el relleno de la vista táctil. No me gusta esto como una solución porque puede ser difícil hacer un seguimiento de cómo se están cambiando de tamaño las Vistas.

+1

Intenté anular el getHitRect pero parece que no funciona (no se llama en absoluto). Básicamente, creo una vista personalizada que amplía un ImageButton y luego, en la clase, anulo el getHitRect (con relleno adicional) pero como mencioné, getHitRect nunca recibe una llamada. ¿Es posible publicar su solución? – stephenteh

+2

Resulta que la solución que ofrecí no funciona en ICS, podría ser por eso que no está funcionando para usted. Escribí una publicación en el blog sobre dos estrategias diferentes para delegados táctiles http://www.brendanweinstein.me/2012/06/26/touchdelegate-and-gethitrect-making-buttons-with-expanded-touch-areas/ y puede obtener muestras código para ambas estrategias en https://github.com/brendanw/Touch-Delegates/blob/master/src/com/brendan/touchdelegates/MyTouchDelegate.java –

+0

Esto no responde la pregunta de OP. OP no intenta agregar múltiples delegados a una vista. Los dos '' ImageButton''s en el ejemplo de OP tienen * diferentes * padres. – zyamys

0
+0

Tenga en cuenta que las respuestas de solo enlace no se recomiendan, por lo que las respuestas deben ser el punto final de una búsqueda de una solución (frente a otra escala de referencias, que tienden a quedarse obsoletas en el tiempo). Considere agregar una sinopsis independiente aquí, manteniendo el enlace como referencia. – kleopatra

15

patrón compuesto que puede utilizar para poder añadir más de un TouchDelegate a la vista.Pasos:

  1. Crear TouchDelegateComposite (no importa qué ver pasará como argumento , se utiliza sólo para obtener el Contexto)
  2. Crear TouchDelegates necesarias y agregarlos al compuesto
  3. Añadir compuesta de Ver como ellos recomiendan here (a través de view.post (nueva Ejecutable))

    public class TouchDelegateComposite extends TouchDelegate { 
    
        private final List<TouchDelegate> delegates = new ArrayList<TouchDelegate>(); 
        private static final Rect emptyRect = new Rect(); 
    
        public TouchDelegateComposite(View view) { 
         super(emptyRect, view); 
        } 
    
        public void addDelegate(TouchDelegate delegate) { 
         if (delegate != null) { 
          delegates.add(delegate); 
         } 
        } 
    
        @Override 
        public boolean onTouchEvent(MotionEvent event) { 
         boolean res = false; 
         float x = event.getX(); 
         float y = event.getY(); 
         for (TouchDelegate delegate : delegates) { 
          event.setLocation(x, y); 
          res = delegate.onTouchEvent(event) || res; 
         } 
         return res; 
        } 
    
    } 
    
+0

Esta es una solución mucho mejor, no tiene una jerarquía de vistas desordenada llena de vistas de envoltura o está jugando con el relleno, y no es necesario crear vistas de subclases para anular el método getHitRect(). Una sugerencia menor sería incorporar el método expandTouchArea() de la respuesta de @Brendan Weinstein a esta clase por el bien de la pulcritud/facilidad. – AndroidNoob

+2

He adaptado esta solución para expandir el área de vistas clicable con el mismo padre: [gist] (https://gist.github.com/nikosk/3854f2effe65438cfa40) @AndroidNoob: incluye un método estático para facilitar su uso. Usado así: TouchDelegateComposite.expandClickArea (buttonView, parentView, clickListener, paddingInDP); – javito

+0

Esto no responde la pregunta de OP. OP no intenta agregar múltiples delegados a una vista. Los dos '' ImageButton''s en el ejemplo de OP tienen * diferentes * padres. – zyamys

0

Para que su código de trabajo que necesita para disminuir el borde izquierdo de bounds2, y no aumentarlo.

bounds2.left -= 50; 

Después de jugar un poco con TouchDelegate, llegué a la siguiente código, que funciona para mí todo el tiempo en cualquier versión de Android. El truco consiste en ampliar el área garantizada después de que se llame al diseño.

public class ViewUtils { 

    public static final void extendTouchArea(final View view, 
      final int padding) { 

     view.getViewTreeObserver().addOnGlobalLayoutListener(
       new OnGlobalLayoutListener() { 

      @Override 
      @SuppressWarnings("deprecation") 
      public void onGlobalLayout() { 
       final Rect touchArea = new Rect(); 
       view.getHitRect(touchArea); 
       touchArea.top -= padding; 
       touchArea.bottom += padding; 
       touchArea.left -= padding; 
       touchArea.right += padding; 

       final TouchDelegate touchDelegate = 
        new TouchDelegate(touchArea, view); 
       final View parent = (View) view.getParent(); 
       parent.setTouchDelegate(touchDelegate); 

       view.getViewTreeObserver().removeGlobalOnLayoutListener(this); 
      } 
     }); 
    } 

} 
0

bien supongo que nadie tiene la respuesta real para hacer una solución de la misma y que sea easy.Lately i tenía misma edición y la lectura de todo lo anterior sólo tenía ni idea de cómo sólo para que sea work.But finalmente lo hice Lo primero que debe tener en mente! Supongamos que tiene un diseño completo que tiene sus dos botones pequeños, que área debe ampliarse, por lo que DEBE hacer otro diseño dentro de su diseño principal y poner otro botón a su diseño recién creado, por lo en ese caso, con el método estático, puedes delegar el tacto en 2 botones al mismo tiempo. ¡Ahora más profundamente y paso a paso en el código! primera seguramente acaba de encontrar el punto de vista de su mainLayout y Button como este. (En este diseño se llevará a cabo nuestro primer botón)

RelativeLayout mymainlayout = (RelativeLayout)findViewById(R.id.mymainlayout) 
Button mybutoninthislayout = (Button)findViewById(R.id.mybutton) 

bien hemos hecho encontrar el diseño principal y su vista botón que llevará a cabo todo lo que es sólo nuestra onCreate() mostrando el diseño, pero tiene que encontrarlo en caso de usarlo más tarde. ¿Qué sigue? Creamos otro RelativeLayout dentro de nuestro diseño principal cuyo ancho y alto es de su gusto (este diseño recién creado tendrá nuestro segundo botón)

RelativeLayout myinnerlayout = (RelativeLayout)findViewById(R.id.myinnerlayout) 
Button mybuttoninsideinnerlayout = (Button)findViewById(R.id.mysecondbutton) 

ok, hemos hecho la búsqueda de vistas, así que ahora solo podemos copiar y pegar la c oda de nuestro hombre que primero respondió su pregunta. Simplemente copie ese código dentro de su actividad principal.

public static void expandTouchArea(final View bigView, final View smallView, final int extraPadding) { 
    bigView.post(new Runnable() { 
     @Override 
     public void run() { 
      Rect rect = new Rect(); 
      smallView.getHitRect(rect); 
      rect.top -= extraPadding; 
      rect.left -= extraPadding; 
      rect.right += extraPadding; 
      rect.bottom += extraPadding; 
      bigView.setTouchDelegate(new TouchDelegate(rect, smallView)); 
     } 
    }); 
} 

Ahora, ¿cómo utilizar este método y hacerlo funcionar? Aquí es cómo! de su método onCreate() pegar el siguiente fragmento de código

expandTouchArea(mymainlayout,mybutoninthislayout,60); 
    expandTouchArea(myinnerlayout, mybuttoninsideinnerlayout,60); 

Explicación de lo que hicimos en este snipped.We tomó nuestro método estático creado nombrado expandTouchArea() y dio 3 argumentos. primer argumento: el diseño que contiene el botón, qué área debe ampliarse 2do argumento: botón real para expandir el área 3er argumento: ¡el área en píxeles de cuánto queremos que se expanda el área del botón! ¡DISFRÚTELO!

0

que tenían el mismo problema: se trata de añadir múltiples TouchDelegates para diferentes eventos que LinearLayouts ruta táctiles para separar Switches respectivamente, en un solo diseño.

Para obtener más información, consulte this question asked by me y my answer.

Lo que encontré es: Una vez Adjunto la LinearLayouts cada una por otra LinearLayout, respectivamente, el segundo (al final todos los otros sucesivos) TouchDelegate empieza a funcionar como se espera.

Esto podría ayudar al OP a crear una solución de trabajo para su problema. No tengo una explicación satisfactoria sobre por qué se comporta así, sin embargo.