API Canvas de Android Explicación detallada (Parte 2) Colección de métodos de corte

Introducción a esta sección:

Esta sección continúa brindando la Explicación detallada de la API de Canvas (Parte 2) de la Explicación detallada de la serie de dibujos de Android. ¡Hoy explicaremos la familia de métodos ClipXxx en Canvas! Podemos ver que hay tres tipos de métodos Clip proporcionados en el documento:  clipPath ( ), clipRect ( ), clipRegion ( );

¡A través de diferentes combinaciones de Path, Rect y Region, se puede admitir casi cualquier forma de área de recorte!

Camino : Puede ser una curva abierta o cerrada, un conjunto complejo de gráficos compuestos por líneas

Recto : área rectangular

Región : Se puede entender como una combinación de regiones. Por ejemplo, ¡dos regiones se pueden sumar, restar y confundir!

Region.Op define los tipos de operaciones interregionales compatibles con Region! Hablaremos de eso más adelante, y otra cosa que decir, el recorte que generalmente entendemos puede ser recortar los gráficos existentes, pero en Android, el recorte del lienzo debe realizarse antes de dibujar la imagen. dibujo Si realiza Clip, no afectará a los gráficos ya dibujados. ¡Recuerde que Clip es para Canvas, no para gráficos! Bueno, no BB, ¡solo comienza esta sección!

Documentación oficial de la API : Canvas


1. Explicación detallada del método de combinación Region.Op

De hecho, la dificultad no es más que esto: Region representa una región, lo que significa un área cerrada determinada en la capa Canvas. Por supuesto, cuando tenga tiempo, puede deducir lentamente esta clase usted mismo, y generalmente solo prestamos atención a uno de sus valores de enumeración: Op

Echemos un vistazo a la función de cada valor de enumeración: asumimos dos regiones de recorte A y B, luego llamamos al valor de enumeración correspondiente a Region.Op:

DIFERENCIA : El rango de diferencia de A y B , es decir, A - B, solo se mostrará el contenido del dibujo dentro de este rango;

INTERSECCIÓN : es decir, el rango de intersección de A y B , solo se mostrará el contenido del dibujo dentro de este rango

UNION : Es decir, se mostrará el rango de unión de A y B , es decir, se mostrará el contenido del dibujo del rango incluido por ambos;

XOR : el rango complementario de A y B , en este ejemplo, el rango de A excepto B, solo se mostrará el contenido del dibujo dentro de este rango;

REVERSE_DIFFERENCE : El rango de la diferencia entre B y A , es decir, B - A, solo se mostrará el contenido del dibujo dentro de este rango;

REEMPLAZAR : Independientemente del estado de recopilación de A y B, se mostrará en su totalidad el rango de B. Si hay una intersección con A, se cubrirá el rango de intersección de A;

Si ha aprendido colecciones, entonces dibujar un Venn (diagrama de Venn) será claro, ¿no ha aprendido? ¡Está bien, escribamos un ejemplo para probar el resultado correspondiente~! Escribe un método para inicializar el pincel y dibujar un rectángulo:

private void init() { 
    mPaint = new Paint(); 
    mPaint.setAntiAlias(verdadero); 
    mPaint.setStrokeWidth(6); 
    mPaint.setColor(getResources().getColor(R.color.blush)); 
} 

drawScene vacío privado (lienzo del lienzo) { 
    canvas.drawRect (0, 0, 200, 200, mPaint); 
}

OP.DIFERENCIA :

canvas.clipRect(10, 10, 110, 110); //el primer 
canvas.clipRect(50, 50, 150, 150, Region.Op.DIFFERENCE); //el segundo 
drawScene(canvas);

resultado :

A partir de (10,10) y (50,50) sucesivamente, se recortaron dos rectángulos de 100*100 y el resultado del recorte es:

La diferencia de A y B = A - (la intersección de A y B)


Op.INTERSECCIÓN :

canvas.clipRect(10, 10, 110, 110); //el primer 
canvas.clipRect(50, 50, 150, 150, Region.Op.INTERSECT); //el segundo 
drawScene(canvas);

resultado :

Comenzando en (10,10) y (50,50) sucesivamente, se recortan dos rectángulos de 100*100 y el resultado del recorte es:  Intersección de A y B = Parte de intersección de A y B


Op. UNIÓN :

canvas.clipRect(10, 10, 110, 110); //el primer 
canvas.clipRect(40, 40, 140, 140, Region.Op.UNION); //el segundo 
drawScene(canvas);

resultado :

Partiendo de (10,10) y (50,50) sucesivamente, se recortan dos rectángulos de 100*100, y el resultado del recorte es:  unión de A y B = área de A + área de B


Op. XOR :

canvas.clipRect(10, 10, 110, 110); //el primer 
canvas.clipRect(50, 50, 150, 150, Region.Op.XOR); //el segundo 
drawScene(canvas);

resultado :

Comenzando en (10,10) y (50,50) sucesivamente, se recortan dos rectángulos de 100*100 y el resultado del recorte es: Conjunto complementario de A y B =  conjunto de A y B - conjunto de intersección de A y B


Op.REVERSE_DIFFERENCE :

canvas.clipRect(10, 10, 110, 110); //el primer 
canvas.clipRect(50, 50, 150, 150, Region.Op.REVERSE_DIFFERENCE); //el segundo 
drawScene(canvas);

resultado :

Comenzando en (10,10) y (50,50) sucesivamente, se recortan dos rectángulos de 100*100 y el resultado del recorte es:  diferencia de B y A = B - intersección de A y B


OP.REEMPLAZAR

canvas.clipRect(10, 10, 110, 110); //el primer 
canvas.clipRect(50, 50, 150, 150, Region.Op.REPLACE); //el segundo 
drawScene(canvas);

resultado :

Comenzando en (10,10) y (50,50) sucesivamente, corte dos rectángulos de 100*100, el resultado del corte es: Independientemente del  estado de la colección de A y B, el rango de B se mostrará en su totalidad, si Si hay una intersección con A, se cubrirá el rango de intersección de A;


2. Ejemplo de uso de Region.Op:

Los ejemplos se refieren a: Android 2D Graphics Learning (2), Canvas Part 2, Canvas Clipping and Region, RegionIterator

Diagrama de efecto de carrera :

La parte clave del código MyView.java:

/** 
 * Creado por Jay el 10/11/2015 0010. 
 */ 
public class MyView extends View{ 

    private Bitmap mBitmap = null; 
    private int limitLength = 0; // 
    private int ancho; 
    private int altura; 
    private static final int CLIP_HEIGHT = 50; 

    estado booleano privado = HIDE;//Mostrar u ocultar el estado, el primero es HIDE 
    private static final boolean SHOW = true;//Mostrar la imagen 
    private static final boolean HIDE = false;//Ocultar la imagen 

    public MyView( Contexto context ) { 
        this(context, null); 
    } 

    public MyView(Context context, AttributeSet attrs) { 
        super(context, attrs);
        mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.img_meizi); 
        limitLength = ancho = mBitmap.getWidth(); 
        altura = mBitmap.getHeight(); 
    } 

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) { 
        super(context, attrs, defStyleAttr); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
        Region region = new Region(); 
        int i = 0; 
        while (i * CLIP_HEIGHT <= altura) {//计算clip的区域
            if (i % 2 == 0) { 
                region.union(new Rect(0, i * CLIP_HEIGHT, limitLength, (i + 1) * CLIP_HEIGHT)) ; 
            } demás {
                region.union(nuevo Rect(ancho - limitLength, i * CLIP_HEIGHT, ancho, (i + 1) 
                        * CLIP_HEIGHT)); 
            } 
            i++; 
        } 
        canvas.clipRegion(región); 
        canvas.drawBitmap(mBitmap, 0, 0, new Paint()); 
        if (status == HIDE) {//Si 
            limitLength está oculto en este momento -= 10; 
            if(limitLength <= 0) 
                status=SHOW; 
        } else {//Si 
            limitLength se muestra en este momento += 5; 
            if(limitLength >= ancho) 
                estado=OCULTAR; 
        } 
        invalidar(); 
    } 
}

Realizar análisis :

Obtenga el ancho y la altura durante la inicialización, y luego haga un bucle. Se puede entender que la imagen se divide en líneas. La condición del bucle es: i * la altura de cada línea no es mayor que la altura, y luego las líneas se dividen en dos casos. Se llama la unión de la región. De hecho, es solo el método de corte de UNINO. Finalmente, juzga si la imagen se muestra en este momento, y maneja las situaciones ocultas y mostradas de manera diferente, y finalmente llama a invalidar ( ) para redibujar! Es bastante simple, entiéndelo por ti mismo~

Otra cosa que decir: la transformación de Canvas no tiene efecto en clipRegion


3. Explicación detallada del método clipRect:

clipRect proporciona siete métodos sobrecargados:

Los parámetros se introducen de la siguiente manera :

rect : objeto Rect, utilizado para definir el rango del área de recorte, Rect y RectF tienen funciones similares, pero la precisión y los métodos proporcionados son diferentes

izquierda : la posición izquierda del área de recorte rectangular

top : la posición superior del área de recorte rectangular

right : la posición correcta del área de recorte rectangular

bottom : la posición inferior del área de recorte rectangular

op : el método de combinación del área de recorte

Los cuatro valores anteriores pueden ser de coma flotante o enteros

Ejemplo de uso :

mPaint = new Paint(); 
mPaint.setAntiAlias(true); 
mPaint.setColor(Color.BLACK); 
mPaint.setTextSize(60); 

canvas.translate(300,300); 
canvas.clipRect(100, 100, 300, 300); //Establecer el rango de visualización 
canvas.drawColor(Color.WHITE); //Fondo blanco 
canvas.drawText("Doble 11, sigue comiendo mi comida para perros...", 150, 300, mPaint); //Dibujar una cuerda

Resultado de la ejecución :

Del ejemplo anterior, no sé si lo encontraste. clipRect se verá afectado por la transformación de Canvas, y el área blanca es el área que no gasta, entonces, lo que clipRect recorta es el lienzo, ¡y nuestro dibujo se realiza en este lienzo recortado! ¡Exceder esta área no se mostrará!


4. Explicación detallada del método clipPath:

En comparación con clipRect, clipPath tiene solo dos métodos sobrecargados, y el método de uso es muy simple, ¡simplemente dibuje una Ruta usted mismo y pásela!

Ejemplo de uso :

Aquí hay un ejemplo de cómo reutilizar el ImageView circular que escribimos en ImageView antes ~

Código de implementación :

Vista de imagen personalizada: RoundImageView.java

/** 
 * Creado por coder-pig el 2015/7/18 0018. 
 */ 
public class RoundImageView extends ImageView { 

    private Bitmap mBitmap; 
    privado Rect mRect = new Rect(); 
    PaintFlagsDrawFilter privado pdf = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG); 
    pintura privada mPaint = nueva pintura (); 
    ruta privada mPath=nueva ruta(); 
    RoundImageView público (contexto contexto, AttributeSet attrs) { 
        super (contexto, attrs); 
        en eso(); 
    } 


    //传入一个Bitmap对象
    public void setBitmap(Bitmap bitmap) { 
        this.mBitmap = bitmap; 
    } 


    init vacío privado () { 
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setFlags(Paint.ANTI_ALIAS_FLAG); 
        mPaint.setAntiAlias(true);// 抗锯尺
    } 


    @Override 
    protected void onDraw(Canvas canvas) { 
        super.onDraw(canvas); 
        if(mBitmap == null) 
        { 
            retorno; 
        } 
        mRect.set(0,0,obtenerAncho(),obtenerAltura()); 
        lienzo.guardar(); 
        lienzo.setDrawFilter(pdf); 
        mPath.addCircle(getWidth() / 2, getWidth() / 2, getHeight() / 2, Path.Direction.CCW); 
        canvas.clipPath(mPath, Region.Op.REPLACE); 
        canvas.drawBitmap(mBitmap, null, mRect, mPaint);
        lienzo.restaurar(); 
    } 
}

Código de diseño: activity_main.xml :

<com.jay.demo.imageviewdemo.RoundImageView 
        android:id="@+id/img_round" 
        android:layout_width="200dp" 
        android:layout_height="200dp" 
        android:layout_margin="5px"/>

MainActivity.java :

Clase pública MainActivity extiende AppCompatActivity { 

    Private RoundImageView img_round; 

    @Override 
    protected void onCreate(Paquete de estado de instancia guardado) { 
        super.onCreate(estado de instancia guardado); 
        setContentView(R.diseño.actividad_principal); 
        img_round = (RoundImageView) findViewById(R.id.img_round); 
        Mapa de bits mapa de bits = BitmapFactory.decodeResource(getResources(),R.mipmap.meinv); 
        img_round.setBitmap(mapa de bits); 
    } 
}

Además, el ImageView redondeado creado con este método tendrá un alias obvio. Incluso si configura el suavizado para Paint y Canvas, es inútil ~ Si tiene requisitos altos, puede usar Xfermode-PorterDuff para configurar la mezcla de imágenes para lograrlo. Básicamente no hay alias Visible: Paint API de Android - Explicación detallada de Xfermode y PorterDuff (3)

Supongo que te gusta

Origin blog.csdn.net/leyang0910/article/details/131828049
Recomendado
Clasificación