Estoy escribió un custom View Android que necesita para dibujar fuera de sus Límites de recorte.

Esto es lo que tengo:

Cuando el dibujo fuera de la vista clip de límites con Android: ¿cómo puedo evitar que las originaron vistas de dibujo en la parte superior de mi vista personalizada?

Esto es lo que pasa cuando hago clic en un botón, dicen que el botón de la derecha:

Cuando el dibujo fuera de la vista clip de límites con Android: ¿cómo puedo evitar que las originaron vistas de dibujo en la parte superior de mi vista personalizada?

¿Cómo puedo prevenir la Vista de abajo para dibujar en la parte superior de mi «mango»?

Algunos relacionados con el pseudo-código de mi proyecto siga.

Mi vista personalizada MyHandleView dibujar como este:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Path p = mPath;
    int handleWidth = mHandleWidth;
    int handleHeight = mHandleHeight;
    int left = (getWidth() >> 1) - handleWidth;

    canvas.save();

    //allow drawing out of bounds vertically
    Rect clipBounds = canvas.getClipBounds();
    clipBounds.inset(0, -handleHeight);
    canvas.clipRect(clipBounds, Region.Op.REPLACE);

    //translate up to draw the handle
    canvas.translate(left, -handleHeight);

    //draw my background shape
    canvas.drawPath(p, mPaint);

    canvas.restore();
}

El diseño es algo como esto (he simplificado un poco):

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Main content of the SlidingUpPanel -->
    <fragment
        android:above=@+id/panel"
        class="com.neosperience.projects.percassi.android.home.HomeFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="?android:attr/actionBarSize"
        tools:layout="@layout/fragment_home" />

    <!-- The Sliding Panel -->
    <LinearLayout
        android:id="@id/panel"
        android:layout_width="match_parent"
        android:layout_height="@dimen/myFixedSize"
        android:alignParentBottom="true"
        android:orientation="vertical"
        android:clipChildren="false">

        <MyHandleView  xmlns:custom="http://schemas.android.com/apk/res-auto.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            custom:handleHeight="@dimen/card_panel_handle_height"
            custom:handleWidthRatio="@dimen/card_panel_handle_width_ratio"
            custom:handleBackgroundColor="#000"/>

        <TextView
            android:id="@+id/loyaltyCardPanelTitle"
            android:layout_width="match_parent"
            android:layout_height="@dimen/card_panel_height"
            android:background="#000"
            android:gravity="center"
            android:textStyle="bold"
            android:textSize="24sp"
            android:textColor="#fff"
            android:text="My TEXT"/>
    </LinearLayout>

</RelativeLayout>

Se puede pensar en el fragmento como una vista que contiene dos botones en la parte inferior, en un LinearLayout.

En lugar de la externa RelativeLayout realmente estoy utilizando una vista de una biblioteca: SlidingUpPanelLayout (https://github.com/umano/AndroidSlidingUpPanel). Pero he probado el comportamiento con este RelativeLayout: la misma cosa, es decir, la biblioteca no está relacionado.

Digo esto sólo para hacerle saber que yo no puedo solo lugar hay un FrameLayout y evitar dibujo fuera de los límites de recorte.

Sospecho que esto tiene algo que ver con el hecho de que cuando me toque el botón de dibujarse, pero mi otro punto de vista (que está en otro lugar en la jerarquía) no se re-dibujado (esta es una optimización y dudo que se puede desactivar).

Me gustaría ser capaz de invalidar mi vista personalizada cada vez que cualquier otra «cerca» (o cualquier) de la vista de obtener la invalidado, por lo tanto necesito algún tipo de oyente en vista de invalidación pero yo no soy consciente de ninguna.

Alguien puede ayudarme?

  • yo todavía no entiendo por qué no desea que la parte inferior de la vista de superposición de los dos botones de arriba…
  • No es que yo no lo quiero. No puedo. El SlildeUpPanel biblioteca requiere tener 2 hijos. El primero es el contenido principal (el que tiene los dos botones) el segundo es el contenido que se deslice hacia arriba. Puedo usar un FrameLayout y ponerlo todo correctamente pero luego no se mueva en absoluto. Por lo tanto la única otra opción sería escribir mi propia versión de la diapositiva en el panel o el parche de la que yo estoy usando. Me gustaría evitar, porque es un montón de trabajo.

1 Comentario

  1. 85

    He encontrado la solución a mí mismo, incluso si esta no es la óptima para las actuaciones.

    Acaba de agregar:

    android:clipChildren="false"

    para el RelativeLayout (o cualquier diseño que usted tenga).

    Este tiene 2 efectos (puede ser más, estos son los dos que me interesa):
    – el ViewGroup no recortar el dibujo de sus hijos (obvio)
    – el ViewGroup no comprobar la intersección con la sucia regiones (invalida) al considerar que los niños a dibujar

    Escarbé el código de la Vista sobre invalidantes.

    Que el proceso se va, más o similares, como este:

    1. una Vista invalida a sí misma, la región se suele dibujar (rectangular) se convierten en un «sucio región» para ser redrawed
    2. la Vista de decirle a su padre (un ViewGroup de algún tipo) deben dibujarse
    3. los padres hacer lo mismo con su padre a la raíz
    4. cada uno de los padres en la jerarquía de bucle para todos los niños y comprobar si el sucio región se cruzan algunos de ellos
    5. si no también dibuje de nuevo

    En el paso 4 de recorte está involucrado: el ViewGroup de verificación de la vista de los límites de su hijo sólo si clipChildren es cierto: lo que significa que si se coloca a es falso, se siempre redibujar todos sus hijos cuando cualquiera de ellos se invalida.

    Así, mi punto de Vista de la jerarquía era como este:

    ViewGroup A
    |
    |----- fragment subtree (containing buttons, map,
    |       whatever element that I don't want to draw
    |       on top of my handle)
    |
    |----- ViewGroup B
           |
           |---- my handle (which draw outside its clip bounds)

    En mi caso el «mango» dibujar ouf de que es obligado, en la parte superior de algo que generalmente se toman por algún elemento del fragmento de subárbol.

    Cuando cualquier punto de vista en el interior del fragmento es invalidado pasar su «sucio región» en la vista de árbol y cada grupo vista de comprobar si hay otros niños a ser redibujado en esa región.

    ViewGroup B clip de lo que dibujo fuera del clip de límites si no me fije clipBounds=»false» en él.

    Si nada es invalidado en el fragmento subárbol la ViewGroup Un verá que ViewGroup B sucio región no es la intersección entre el fragmento de subárbol de la región y se saltan el nuevo trazado de ViewGroup B.

    Pero si digo también ViewGroup Un a no de clip de niños que todavía va a dar ViewGroup B un invalidar el comando que va a provocar un rediseño de mi mango.

    Así que la solución es asegurarse de establecer

    android:clipChildren="false"

    en cualquier ViewGroup en la jerarquía por encima de la Opinión de que el empate fuera de los límites en los que el contenido puede caer «bajo» el fuera-de-bound región en la que está el dibujo.

    El obvio efecto secundario de esto es que cada vez que me invalidar cualquiera de la vista dentro de Un ViewGroup un invalidar llamada será transferida, con la válida de la región, a todos los de la vista en ella.

    Sin embargo, cualquier punto de vista que no cruzan el sucio de la región que está dentro de un ViewGroup con clipChildren=»true» (por defecto) se omitirá.

    Así que para evitar problemas de rendimiento al hacer esto, asegúrese de que su visión de los grupos con clipChildren=»true» no tiene muchos «estándar» hijos directos. Y con el «estándar», me refiero a que no quieren sacar fuera de su vista los límites.

    Así, por ejemplo, si en mi ejemplo ViewGroup B contiene muchas de vista de considerar la posibilidad de envolver a todos aquellos que en un ViewGroup con clipChildren=»true» y solo dejar este grupo vista y el punto de vista de que dibujar fuera de su región como hijos directos de ViewGroup B. lo mismo ocurre para ViewGroup A.

    Este simple hecho asegúrese de que no hay otro punto de Vista recibirá un rediseño si no están en la invalidado sucio de la región de minimizar el redibuja necesario.

    Todavía estoy abierto a escuchar más consideración si alguien tiene uno 😉

    Así que voy a esperar un poco antes de la celebración de este aceptado como respuesta.

    EDICIÓN: Muchos dispositivos de hacer algo diferente en el manejo de clipChildren=»false». Descubrí que tenía para establecer clipChildren=»false» en todos los puntos de vista de los padres de mi widget personalizado que puede contener elementos en su jerarquía que debería atraer a más de los «fuera de juego a la región» del widget o usted puede ver su dibujo personalizadas mostrando EN la parte SUPERIOR de otro punto de vista que se supone que iba a cubrir. Por ejemplo, en mi diseño, yo tenía un Cajón de Navegación que se suponía que era para cubrir mi «mango». Si no he puesto clipChildren=»false» en el NavigationDrawer diseño me puede a veces ver a mi manejar pop up en la parte delantera de la abrió la gaveta.

    EDIT2: Mi widget personalizado tenían 0 altura y dibujada por «encima» de sí mismo. Trabajó muy bien en los dispositivos Nexus, pero muchos de los otros se habían algunos «optimización» en lugar de que salte el dibujo de las vistas que tienen 0 alto o 0 ancho. Por lo que ser conscientes de esto si quieres escribir un componente que sacar de encuadernado: usted tiene que asignar al menos de 1 píxel de ancho /alto.

    • ningún otro de los encuestadores, eh? ya que esto parece que funciona bastante bien, incluso en actuaciones que marca esta aceptado como respuesta
    • Que no me funciona 🙁
    • Dudo mucho que 🙂 me escribió una detallada explicación sobre cómo funciona y cuando tenga sentido. Usted probablemente está en una situación diferente.
    • Sí tal vez. Pero gracias por la actualización, te lo agradezco 😉
    • Trabajó para mí. Problema Similar. Vista personalizada añadido a un FrameLayout. Cuando se mueve fuera de la pantalla y, a continuación, volver, sería permanecer parcialmente recortada. También si se rota fuera de la pantalla, el uso de métodos setrotation y setPivotX y setPivotY. Cuando la rotación trajo de vuelta en la pantalla se quedó cortado. A pesar de que es ‘onDraw ()» fue llamado. llamar setClipChildren(false) en mi FrameLayout funcionaba bien. Tengo otra lógica para prevenir el ‘dibujo’ si está demasiado lejos fuera de la pantalla. Gracias.

Dejar respuesta

Please enter your comment!
Please enter your name here