実用的なAndroidビットマップエクスペリエンス



少し前、勤務中に、1つのタスクに直面しました。Android用のメディアプレーヤーの設計を考え出し、実装する必要がありました。 そして、もしあなたがコントロールと情報の多かれ少なかれ許容できる配置を考えて整理するなら、それはトリッキーなものではないことが判明しました、そしてデザインにいくらかの熱意をもたらすために、私は慎重に考えなければなりませんでした。 幸いなことに、メロディのアルバムカバー付きの写真などの要素がありました。 全体像に色を加えるのは彼でした。

しかし、ボタンと碑文の間に単純に表示されているため、カバーは画面に貼り付けられた紙のステッカーのように見えました。 ここでは画像処理なしではできないことに気付きました。



発明された可能性のあるものについてのいくつかの考えは、カバー画像の反射と影の効果を作る決定をもたらしました。 リフレクションの実際的な実装は、私の最初のアイデアではないことをすぐに言わなければなりません。 発見された英語の記事で彼女をスパイした。 この投稿では、画像に対して実行された操作、処理プロセスへの追加について理解し、AndroidでBitmapを使用する際の微妙な違いに注目したいだけです。

それで、入り口に、写真付きのビットマップがありました。 最初に、元の画像と同じサイズの空のビットマップを作成しました。これは、後で同じカバーとなるはずでしたが、影が適用されています。

width = sourceBitmap.getWidth(); height = sourceBitmap.getHeight(); Bitmap gradCover; try { gradCover = Bitmap.createBitmap(width, height, config); } catch (OutOfMemoryError e) { gradCover = null; }
      
      





このメソッドは、可変(重要)ビットマップを作成します。

ここで、ビットマップを使用する場合、メモリを注意深く監視する必要があることに注意してください。 例外をキャッチする必要があります。 そしてもう1つ、プロファイラーによる調査では、createBitmap()メソッドを呼び出す前にガベージコレクターが機能することが示されました。 アプリケーションで速度が重要な場合は、このことに留意してください。



次に、キャンバスを作成し、元の画像を適用しました。

 Canvas canvas = new Canvas(gradCover); canvas.drawBitmap(sourceBitmap, 0, 0, null); //Free up memory, associated with the original bitmap sourceBitmap.recycle();
      
      





この時点で、私は常に、ビットマップが不要になったらすぐに、recycle()メソッドによって破棄する必要があることに注意します。 実際、このタイプのオブジェクトは、イメージ自体を含むメモリへの単なるリンクであり、ガベージコレクターにとっては非常に小さく見えます(実際、多くのメモリが占​​有されています)。 これは、メモリが最も不適切な瞬間になくなるという事実につながる可能性があります。



すべての準備が完了した後、キャンバスに影付きのペイントを配置します。

 Paint paint = new Paint(); int[] colors = {0xffffffff, 0xffffffff, 0xb0c0c0c0, 0xb0c0c0c0}; float radius = (((float) width * (float) width) / 4 + (float) height * (float) height) / ((float) width); int fullRadius = (int) (1.92 * radius); float[] positions = {0, 0.499f, 0.511f, 1}; RadialGradient shader = new RadialGradient((width - radius), 0, fullRadius, colors, positions, Shader.TileMode.CLAMP); paint.setShader(shader); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); canvas.drawRect(0, 0, width, height, paint); int[] linColors = {0x00ffffff, 0xffffffff, 0xff000000, 0x00000000}; float[] linPositions = {0, 0.03f, 0.97f, 1}; LinearGradient vertical = new LinearGradient(0, 0, 0, height, linColors, linPositions, Shader.TileMode.CLAMP); paint.setShader(vertical); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); canvas.drawRect(0, 0, width, height, paint); LinearGradient horizontal = new LinearGradient(0, 0, width, 0, linColors, linPositions, Shader.TileMode.CLAMP); paint.setShader(horizontal); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); canvas.drawRect(0, 0, width, height, paint);
      
      





私の場合、RadialGradientは、画像の右上隅から下面の中心まで半円に落ちる影を表します。 彼は中心(写真を超えてもよい)、半径、色のシーケンス、および各色の半径に沿った中心からの距離を設定する必要があります。 影には、半径の色のアルファ変化が使用されました。

LinearGradientは、画像の端をフェードするために使用されました。 そのアプリケーションはRadialGradientと非常に似ています。 グラデーションが進む線の始点と終点、この線上の色とその位置を指定する必要があります。



最後に、私は反射を描き始めました。 この時点で、既にgradBitmapが適用されたビットマップがありました。 繰り返しますが、キャンバスを作成し、空の画像(今回は元の画像よりも3倍長い)を作成し、キャンバスに配置して、その上に影付きのビットマップを配置する必要がありました。

 Bitmap refCover = Bitmap.createBitmap(width, height + height / 3, Bitmap.Config.ARGB_8888); Canvas refCanvas = new Canvas(refCover); refCanvas.drawBitmap(gradCover, 0, 0, null);
      
      







短い準備の後、楽しみが始まりました。 画像を下から上に反転するマトリックスを作成しました。 その助けを借りて、ソースの3分の1からビットマップを作成し、元の画像の下のキャンバスに配置しました。

 Matrix matrix = new Matrix(); matrix.preScale(1, -1); Bitmap reflectionImage = Bitmap.createBitmap(gradCover, 0, 2 * height / 3, width, height / 3, matrix, false); refCanvas.drawBitmap(reflectionImage, 0, height, null); reflectionImage.recycle();
      
      





ところで、簡単なメモ:BitmapクラスにはいくつかのcreateBitmapメソッドがあり、そのうちの1つだけが描画可能な可変ビットマップを作成します。 描画用の残りは、それらに適していません。



そして最後に、透明なグラデーションを適用して反射効果を与えます。

 Paint refPaint = new Paint(); LinearGradient refShader = new LinearGradient(0, height, 0, height + height / 3, 0xc0ffffff, 0x00ffffff, Shader.TileMode.CLAMP); refPaint.setShader(refShader); refPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); refCanvas.drawRect(0, height, width, refCover.getHeight() + height, refPaint);
      
      





ペイントは、反射である図面のその部分に適用されます。



それだけです refCover-Bitmapを入手しました。これは、影、滑らかなエッジ、反射を備えたアルバムカバーを示しています。



PSこの記事では、視覚効果を達成することは私にとって重要であったという事実ではなく、それらを取得する方法とそれらに関連するニュアンスです。 誰かのためにここで説明されていることが明らかな場合-結構です。 他の皆さんにとって、この記事がAndroid向けのアプリケーションの作成に役立つことを願っています。



UPD:前後の写真








All Articles