上篇介紹了使用Animation實現3D動畫旋轉翻頁效果,現在介紹圖片倒影實現,先看
本樣本主要通過自訂Gallery和ImageAdapter(繼承自BaseAdapter)實現
1、倒影繪製
ImageAdapter繼承自BaseAdapter,詳細實現可見 Android 滑動效果入門篇(二)—— Gallery 這裡重點介紹倒影原理及實現
倒影原理:
倒影效果是主要由原圖+間距+倒影三部分組成,高度大約為原圖的3/2(原圖為1、倒影為1/2)
原圖,就是我們看到了最開始的圖片
間距,是原圖與倒影之間的間隙,如:reflectionGap = 4;
倒影,是原圖下半部分1/2高度,通過矩陣變換matrix.preScale(1, -1); 擷取倒立圖片,然後再加上線性遮罩和陰影實現
倒影實現:
/** 反射倒影 */<br />public boolean createReflectedImages() {<br />final int reflectionGap = 4;<br />int index = 0;<br />for (Map<String, Object> map : list) {<br />Integer id = (Integer) map.get("image");<br />Bitmap originalImage = BitmapFactory.decodeResource(mContext.getResources(), id);// 擷取原始圖片<br />int width = originalImage.getWidth();<br />int height = originalImage.getHeight();</p><p>Matrix matrix = new Matrix();<br />matrix.preScale(1, -1);// 圖片矩陣變換(從低部向頂部的倒影)<br />Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, height/2, width, height/2, matrix, false);// 截取原圖下半部分<br />Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + height / 2), Config.ARGB_8888);// 建立倒影圖片(高度為原圖3/2)</p><p>Canvas canvas = new Canvas(bitmapWithReflection);// 繪製倒影圖(原圖 + 間距 + 倒影)<br />canvas.drawBitmap(originalImage, 0, 0, null);// 繪製原圖<br />Paint paint = new Paint();<br />canvas.drawRect(0, height, width, height + reflectionGap, paint);// 繪製原圖與倒影的間距<br />canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);// 繪製倒影圖</p><p>paint = new Paint();<br />LinearGradient shader = new LinearGradient(0, originalImage.getHeight(), 0, bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);<br />paint.setShader(shader);// 線性漸層效果<br />paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));// 倒影遮罩效果<br />canvas.drawRect(0, height, width, bitmapWithReflection.getHeight() + reflectionGap, paint);// 繪製倒影的陰影製作效果</p><p>ImageView imageView = new ImageView(mContext);<br />imageView.setImageBitmap(bitmapWithReflection);// 設定倒影圖片<br />imageView.setLayoutParams(new myGallery.LayoutParams(180, 240));<br />imageView.setScaleType(ScaleType.MATRIX);<br />mImages[index++] = imageView;<br />}<br />return true;<br />}
2、myGallery
自訂Gallery來實現倒影圖片的瀏覽與選擇
public class myGallery extends Gallery {</p><p>private Camera mCamera = new Camera();<br />private int mMaxRotationAngle = 60;// 最大旋轉角度 60<br />private int mMaxZoom = -120;<br />private int mCoveflowCenter;</p><p>public myGallery(Context context) {<br />super(context);<br />this.setStaticTransformationsEnabled(true);<br />}</p><p>public myGallery(Context context, AttributeSet attrs) {<br />super(context, attrs);<br />this.setStaticTransformationsEnabled(true);<br />}</p><p>public myGallery(Context context, AttributeSet attrs, int defStyle) {<br />super(context, attrs, defStyle);<br />this.setStaticTransformationsEnabled(true);<br />}</p><p>public int getMaxRotationAngle() {<br />return mMaxRotationAngle;<br />}</p><p>public void setMaxRotationAngle(int maxRotationAngle) {<br />mMaxRotationAngle = maxRotationAngle;<br />}</p><p>public int getMaxZoom() {<br />return mMaxZoom;<br />}</p><p>public void setMaxZoom(int maxZoom) {<br />mMaxZoom = maxZoom;<br />}</p><p>/** 擷取Gallery的中心x */<br />private int getCenterOfCoverflow() {<br />return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2 + getPaddingLeft();<br />}</p><p>/** 擷取View的中心x */<br />private static int getCenterOfView(View view) {<br />return view.getLeft() + view.getWidth() / 2;<br />}</p><p>@Override<br />protected void onSizeChanged(int w, int h, int oldw, int oldh) {<br />mCoveflowCenter = getCenterOfCoverflow();<br />super.onSizeChanged(w, h, oldw, oldh);<br />}</p><p>@Override<br />protected boolean getChildStaticTransformation(View child, Transformation trans) {<br />final int childCenter = getCenterOfView(child);<br />final int childWidth = child.getWidth();<br />int rotationAngle = 0;</p><p>trans.clear();<br />trans.setTransformationType(Transformation.TYPE_BOTH);// alpha 和 matrix 都變換</p><p>if (childCenter == mCoveflowCenter) {// 正中間的childView<br />transformImageBitmap((ImageView) child, trans, 0);<br />} else {// 兩側的childView<br />rotationAngle = (int) ( ( (float) (mCoveflowCenter - childCenter) / childWidth ) * mMaxRotationAngle );<br />if (Math.abs(rotationAngle) > mMaxRotationAngle) {<br />rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle : mMaxRotationAngle;<br />}<br />transformImageBitmap((ImageView) child, trans, rotationAngle);<br />}</p><p>return true;<br />}</p><p>private void transformImageBitmap(ImageView child, Transformation trans, int rotationAngle) {<br />mCamera.save();</p><p>final Matrix imageMatrix = trans.getMatrix();<br />final int imageHeight = child.getLayoutParams().height;<br />final int imageWidth = child.getLayoutParams().width;<br />final int rotation = Math.abs(rotationAngle);</p><p>// 在Z軸上正向移動camera的視角,實際效果為放大圖片; 如果在Y軸上移動,則圖片上下移動; X軸上對應圖片左右移動。<br />mCamera.translate(0.0f, 0.0f, 100.0f);</p><p>// As the angle of the view gets less, zoom in<br />if (rotation < mMaxRotationAngle) {<br />float zoomAmount = (float) (mMaxZoom + (rotation * 1.5));<br />mCamera.translate(0.0f, 0.0f, zoomAmount);<br />}</p><p>mCamera.rotateY(rotationAngle);// rotationAngle 為正,沿y軸向內旋轉; 為負,沿y軸向外旋轉</p><p>mCamera.getMatrix(imageMatrix);<br />imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));<br />imageMatrix.postTranslate((imageWidth / 2), (imageHeight / 2));</p><p>mCamera.restore();<br />}<br />}
3、Activity
Activity中,主要實現自訂Gallery的圖片填充ImageAdapter、myGallery選擇事件監聽、點擊事件監聽
private void initRes(){<br />tvTitle = (TextView) findViewById(R.id.tvTitle);<br />gallery = (myGallery) findViewById(R.id.mygallery);// 擷取自訂的myGallery控制項</p><p>adapter = new ImageAdapter(this);<br />adapter.createReflectedImages();// 建立倒影效果<br />gallery.setAdapter(adapter);</p><p>gallery.setOnItemSelectedListener(new OnItemSelectedListener() {// 設定選擇事件監聽<br />@Override<br />public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {<br />tvTitle.setText(adapter.titles[position]);<br />}</p><p>@Override<br />public void onNothingSelected(AdapterView<?> parent) {<br />}<br />});</p><p>gallery.setOnItemClickListener(new OnItemClickListener() {// 設定點擊事件監聽<br />@Override<br />public void onItemClick(AdapterView<?> parent, View view, int position, long id) {<br />Toast.makeText(Main.this, "img " + (position+1) + " selected", Toast.LENGTH_SHORT).show();<br />}<br />});<br />}
main.xml布局檔案中,通過實現自訂的myGallery,來顯示圖片集合
<?xml version="1.0" encoding="utf-8"?><br /><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"<br /> android:layout_width="fill_parent"<br /> android:layout_height="fill_parent"<br /> android:orientation="vertical" ><br /> <TextView<br /> android:id="@+id/tvTitle"<br /> android:layout_width="wrap_content"<br /> android:layout_height="wrap_content"<br /> android:layout_centerHorizontal="true"<br /> android:textSize="16sp" /></p><p> <com.homer.reflect.myGallery<br /> android:id="@+id/mygallery"<br /> android:layout_width="fill_parent"<br /> android:layout_height="wrap_content"<br /> android:layout_below="@id/tvTitle"<br /> android:layout_marginTop="10dip" /><br /></RelativeLayout>
源碼下載
參考推薦:
Android實現圖片的倒影效果
Android中圖片倒影、圓角效果重繪