『Android群英伝』読書ノート(5)第六章:Android描画メカニズムと処理テクニックの一つ


1.画面パラメータ
  • 画面解像度とDPIの対照表
  • みつど
    ldpi
    mdpi
    hdpi
    xhdpi
    xxhdpi
    みつどち
    120
    160
    240
    320
    480
    解像度
    240x320
    320x480
    480x800
    720x1280
    1080x1920
    2.密度160の画面、すなわち解像度320 x 480の画面で、1 dp=1 px;他の画面では,mdpiでは1 dp=1 px,hdpiでは1 dp=1.5 px,xhdpiでは1 dp=2 px,xxhdpiでは1 dp=3 pxのスケールで計算できる.3.単位換算次のコードはpx、dp、spが互いに変換するツールクラスであり、エンジニアリングに統合して使用することができる.
    public class DisplayUtil{
        public static int px2dp(Context context,float pxValue){
            final float scale = context.getResources().getDisplayMetrics().density;
            return (int)(pxValue / scale + 0.5f);
        }
    
        public static int dp2px(Context context,float dpValue){
            final float scale = context.getResources().getDisplayMetrics().density;
            return (int)(dpValue * scale + 0.5f);
        }
    
        public static int px2sp(Context context,float pxValue){
            final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
            return (int)(pxValue / fontScale + 0.5f);
        }
    
        public static int sp2px(Context context,float spValue){
            final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
            return (int)(spValue * fontScale + 0.5f);
        }
    }

    あるいはAndroidが提供するTypedVauleの方法を使用して実現します.
    protected int dp2px(int dp){
        return (int)TypedVaule.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dp,getResources().getDisplayMetrics());
    }
    
    protected int sp2px(int sp){
        return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,sp,getResources().getDisplayMetrics());
    }

    2.2 D図形描画基礎
    Paintクラスで提供されるいくつかの方法:
    setAntiAlias();//         
    setColor();//       
    setARGB();//     A、R、G、B  
    setAlpha();//     Alpha 
    setTextSize();//       
    setStyle();//       (      Paint.Style.STROKE Paint.Style.FILL)
    setStrokeWidth();//          

    Canvasクラスのいくつかの方法
    canvas.drawPoint(x,y,paint);//  
    canvas.drawLine(startX,startY,endX,endY,paint);//  
    canvas.drawLines(float[] pts,Paint paint);//    
    canvas.drawRect(left,top,right,bottom,paint);//   
    canvas.drawRoundRect(left,top,right,bottom,radiusX,radiusY,paint);//     
    canvas.drawCircle(circleX,circleY,radius,paint);//  
    //  、  
    canvas.drawArc(left,top,right,bottom,startAngle,sweepAngle,useCenter,paint);//startAngle:    ,sweepAngle:     ,useCenter:boolean  , true        ,false       
    canvas.drawText(text,startX,startY,paint);//   
    canvas.drawPosText(text,
            new float[]{X1,Y1,
                        X2,Y2,
                        .....
                        Xn,Yn},
                        paint);//         
    canvas.drawOval(left,top,right,bottom,paint);//   
    Path path = new Path();
    path.moveTo(50,50);
    path.lineTo(100,100);
    path.lineTo(100,300);
    path.lineTo(300,50);
    canvas.drawPath(path,paint);//    

    3.AndroidでのXML描画
    1.Bitmap
    XMLでBitmapを使用するのは簡単です.
    <?xml version="1.0" encoding="utf-8"?>
    <bitmap xmlns:android="http://schemas.android.com/apk/res/android" android:src="@drawable/ic_launcher"/>

    このように1枚の画像を引用することで,画像を直接Bitmapに変換してプログラムで使用することができる.
    2.shape
    ShapeではXMLで任意の形状を描画できます.Shapeでサポートされているパラメータを以下に示します.
    <shape
        xmlns:android="http://schemas.android.com/apk/res/android"
        //   rectangle
        android:shape=["rectangle"|"oval"|"line"|"ring"]>
        <corners // shape="rectangle"   
            //  ,             
            android:radius="integer"
            android:topLeftRadius="integer"
            android:topRightRadius="integer"
            android:bottomLegtRadius="integer"
            android:bottomRightRadius="integer"/>
        <gradient   //  
            android:angle="integer"
            android:centerX="integer"
            android:centerY="integer"
            android:centerColor="color"
            android:endColor="color"
            android:gradientRadius="integer"
            android:startColor="color"
            android:type=["linear"|"radial"|"sweep"]
            android:useCenter=["true"|"false"]/>
        <padding
            android:left="integer"
            android:top="integer"
            android:right="integer"
            android:bottom="integer"/>
        <size //    ,    ImageView  scaleType    
            android:width="integer"
            android:height="integer"/>
        <solid  //    
            android:color="color"/>
        <stroke //    
            android:width="integer"
            android:color="color"
            //    
            android:dashWidth="integer"
            //      
            android:dashGap="integer"/>
    </shape>

    3.Layer
    LayerはPhotoShopで非常によく使われる機能で、Androidでも同様にLayerによって類似の概念を実現することができます
    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <!--   -->
        <item  android:drawable="@drawable/ic_launcher"/>
        <!--   -->
        <item  android:drawable="@drawable/ic_launcher" android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp"/>
    </layer-list>
    layer-listの画像が順次重ねられます
    4.selector
    Selectorの役割は、開発者が静的図面のイベントフィードバックを実現し、異なる画像を設定することで、プログラム内でユーザーの入力に応じて異なる効果を返すことです.
    <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" <!--          --> <item android:drawable="@drawable/X1"/> <!--            --> <item android:state_window_focused="false" android:drawable="@drawable/X2"/> <!--                     --> <item android:state_window_focused="true" android:state_pressed="true" android:drawable="@drawable/X3"/> <!--               --> <item android:state_window_focused="false" android:state_pressed="true" android:drawable="@drawable/X4"/> <!--          --> <item android:state_selected="true" android:drawable="@drawable/X5"/> <!--            --> <item android:state_focused="true" android:drawable="@drawable/X6"/> </selector>

    Selectorはshapeと共同で機能することもできます
    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:state_pressed="true">
            <shape android:shape="rectangle">
                <solid android:color="#33444444"/>
                <corners android:radius="5dp"/>
                <padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp"/>
            </shape>
        </item>
        <item>
            <shape android:shape="rectangle">
                <solid android:color="#FFFFFF"/>
                <corners android:radius="5dp"/>
                <padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp"/>
            </shape>
        </item>
    </selector>

    4.Android描画テクニック
    1.Canvas
    Canvasのいくつかの方法:
    Canvas.save();//
    Canvas.restore();
    Canvas.translate();
    Canvas.rotate();

    Canvas.save()はキャンバスを保存することを意味し、前に描いたすべての画像を保存し、後続の操作を新しいレイヤで操作するようにする役割を果たします.Canvas.restore()は、save()の前に描画された画像と後に描画された画像をマージする動作と理解できる.Canvas.translate()とCanvas.rotate()は、それぞれ平行キャンバスと回転キャンバスであり、座標系の平行移動と回転に似ています.たとえばtranslate(x,y)を呼び出すと原点(0,0)が(x,y)に移動し、その後のすべての操作は(x,y)を原点として実行されます.一般に、Canvasに対してtranslateまたはrotateを呼び出す前にsave()メソッドを呼び出す必要があり、translateまたはrotateメソッドの後のコンテンツの描画が完了した後にrestore()メソッドを呼び出す必要があります.まずAndroid図面の座標系を見てみましょう.座標ゼロ点は画面左上隅にあり、下はY軸正方向、右はX軸正方向です.
    2.Layerレイヤー
    Androidでは、saveLayer()saveLayerAlpha()メソッドを呼び出して1つのレイヤーをスタックに入れ、restore()restoreToCount()メソッドを使用して1つのレイヤーをスタックから出します.スタックに入ると、その後のすべての操作がこのレイヤで発生し、スタックを出ると、画像が上位Canvasに描画されます.次のコードは、Layerの使用方法を示しています.
    @Override
    protected void onDraw(Canvas canvas){
        canvas.drawColor(Color.WHITE);
        mPaint.setColor(Color.BLUE);
        canvas.drawCircle(150,150100,mPaint);
        canvas.saveLayerAlpha(0,0,400,400,127,LAYER_FLAGS);
        mPaint.setColor(Color.RED);
        canvas.drawCircle(200,200,100,mPaint);
        canvas.restore();
    }