Android之——史上最簡單最酷炫的3D圖片瀏覽效果的實現,

來源:互聯網
上載者:User

Android之——史上最簡單最酷炫的3D圖片瀏覽效果的實現,

轉載請註明出處:http://blog.csdn.net/l1028386804/article/details/48052709

如今,Android開發已經成為移動互聯開發領域中一支不可或缺的力量,那麼Android中要實現3D的效果那也就是合情合理的事情了。那麼,如何在Android中實現像IOS中那樣的3D圖片瀏覽效果呢?下面,鄙人將重磅推出今天的重點博文,和大家一起在Android中實現酷炫的3D圖片瀏覽效果。

一、原理

老規矩,還是要來囉嗦下原理的東西。

整體實現是以手機螢幕的正中間位置為對稱軸,位於正中間的圖片顯示最大,也最亮,同時左右兩邊的圖片以最中間位置為對稱軸,分別旋轉對應的角度,同時亮度調整為適當的比例,已達到對稱的效果。具體的3D瀏覽圖片效果,我是通過自訂Gallery來實現的,建立一個類GalleryFlow,繼承Gallery,在這個類中進行映像的旋轉、縮放,亮度設定等操作。同時,在這個類中,我建立了一個相機對象camera來設定映像的變化效果;同時自訂一個映像的適配器類ImageAdapter,這個類繼承BaseAdapter,主要是實現介面圖片的顯示,以及建立帶有倒影的圖片。

原理囉嗦完了,那就讓我們一起來實現這個酷炫的3D效果吧。

二、實現1、自訂配接器ImageAdapter

顯示圖片的適配器,這個類繼承BaseAdapter,完成映像的基本顯示,同時將原有圖片產生帶有倒影的圖片進行顯示。具體的實現為,在構造方法中將介面中的上下文資訊,和存放圖片id的數組傳遞過來,通過傳遞的圖片id數組產生對應的ImageView數組,用來存放帶有圖片資訊的ImageView對象。在createRefectedBitmap()方法中將原有圖片處理成帶有倒影效果的圖片存放在ImageView對象中,然後將ImageView對象存放在ImageView數組中。

具體實現的代碼如下:

package com.lyz.gallery.activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Bitmap.Config;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.LinearGradient;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.PorterDuff.Mode;import android.graphics.PorterDuffXfermode;import android.graphics.Shader.TileMode;import android.graphics.drawable.BitmapDrawable;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;/** * 自訂圖片顯示的適配器ImageAdapter * @author liuyazhuang * */public class ImageAdapter extends BaseAdapter {private Context context;private int[] imageIds;private ImageView[] images;//構造方法public ImageAdapter(Context context, int[] imageIds) {this.context = context;this.imageIds = imageIds;//存放圖片的數組images = new ImageView[imageIds.length];}@Overridepublic int getCount() {return images.length;}@Overridepublic Object getItem(int position) {return images[position];}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {return images[position];}/** * 建立帶有倒影的圖片 */public void createRefectedBitmap() {//原圖片與倒影圖片之間的距離int refectionGap = 4;//向圖片數組中加入圖片for(int i = 0; i < imageIds.length; i++){int imageId = imageIds[i];//原圖片Bitmap resourceBitmap = BitmapFactory.decodeResource(context.getResources(), imageId);int width = resourceBitmap.getWidth();int height = resourceBitmap.getHeight();//倒影圖片//reource:原圖片//x,y:產生倒影圖片的起始位置//width,heiht:產生倒影圖片寬和高//Matrix m:用來設定圖片的樣式(倒影)Matrix m = new Matrix();//x:水平翻轉;y:垂直翻轉   1支援; -1翻轉m.setScale(1, -1);Bitmap refrectionBitmap = Bitmap.createBitmap(resourceBitmap, 0, height / 2, width, height / 2,m, false);//合成的帶有倒影的圖片Bitmap bitmap = Bitmap.createBitmap(width, height + height/2, Config.ARGB_8888);//建立畫布Canvas canvas = new Canvas(bitmap);//繪製原圖片canvas.drawBitmap(resourceBitmap, 0, 0, null);//繪製原圖片與倒影之間的間隔Paint defaultPaint = new Paint();canvas.drawRect(0, height, width, height + refectionGap, defaultPaint);//繪製倒影圖片canvas.drawBitmap(refrectionBitmap, 0, height + refectionGap, null);//ps中的漸層和遮罩效果Paint paint = new Paint();//設定遮罩效果paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));//設定漸層效果//設定著色器為遮罩著色LinearGradient shader = new LinearGradient(0, height, 0, bitmap.getHeight(), 0x70ffffff, 0x00ffffff, TileMode.CLAMP);paint.setShader(shader);canvas.drawRect(0, height, width, bitmap.getHeight(), paint);//建立BitmapDrawable圖片BitmapDrawable bd = new BitmapDrawable(bitmap);//消除圖片鋸齒效果,使圖片平滑bd.setAntiAlias(true);ImageView imageView = new ImageView(context);imageView.setImageDrawable(bd);//設定圖片大小imageView.setLayoutParams(new GalleryFlow.LayoutParams(160, 240));//將圖片放置在images數組中images[i] = imageView;}}}

2、自訂Gallery類GalleryFlow

這個類中我們主要實現的是圖片的縮放、旋轉、亮度調整等操作,下面我們分解來看這個類。

1)成員變數

這裡的成員變數主要是:最大的旋轉角度、最大縮放值、記錄中間點的位置、相機對象

具體實現代碼如下:

//最大的旋轉角度private int maxRotateAngle = 50;//最大縮放值private int maxZoom = -250;//記錄中間點的位置private int currentOfGallery;//建立相機對象private Camera camera = new Camera();

2)構造方法

我在這裡複寫了Gallery的三個構造方法,並在每個構造方法中分別調用了setStaticTransformationsEnabled(true);方法,這個方法的作用是:指定圖形是否變化 false:否  true:是。當我們調用了setStaticTransformationsEnabled方法時,Android就會回調下面的getChildStaticTransformation方法

具體實現代碼如下:

public GalleryFlow(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);setStaticTransformationsEnabled(true);}public GalleryFlow(Context context, AttributeSet attrs) {super(context, attrs);//指定圖形是否變化 false:否  true:是setStaticTransformationsEnabled(true);}public GalleryFlow(Context context) {super(context);setStaticTransformationsEnabled(true);}

3)getChildStaticTransformation方法

這個方法是調用了setStaticTransformationsEnabled時,Android會回調的一個方法,我在這個方法中完成的操作主要是:計算映像的旋轉角度,設定圖片的變形樣式,同時調用圖片變形的放方法transformationBitmap來達到圖片變形的效果。

具體實現的代碼如下:

@Overrideprotected boolean getChildStaticTransformation(View child, Transformation t) {//得到圖片的中心點int currentOfChild = getCurrentOfView(child);int width = child.getLayoutParams().width;int height = child.getLayoutParams().height;//旋轉的角度int rotateAngle = 0;t.clear();//設定圖片變形樣式t.setTransformationType(Transformation.TYPE_MATRIX);//位置中心點位置if(currentOfChild == currentOfGallery){transformationBitmap((ImageView)child, t, 0);}else{//不是中心位置rotateAngle = (int) ((float)(currentOfGallery - currentOfChild) / width * maxRotateAngle);if(Math.abs(rotateAngle) > maxRotateAngle){rotateAngle = rotateAngle < 0 ? -maxRotateAngle : maxRotateAngle;}//圖片變形transformationBitmap((ImageView)child, t, rotateAngle);}return true;}

4)圖片變形方法transformationBitmap

這個方法主要完成的操作就是通過相機對象來完成對映像的變形操作。

具體實現代碼如下:

/** * 圖片變形 * @param child * @param t * @param i */private void transformationBitmap(ImageView child, Transformation t, int rotateAngle) {//儲存映像變化的效果camera.save();Matrix imageMatrix = t.getMatrix();int rotate = Math.abs(rotateAngle);int imageWidth = child.getWidth();int imageHeight = child.getHeight();//z:正數:圖片變大//x:水平移動//y:垂直移動camera.translate(0.0f, 0.0f, 100.0f);//當前旋轉角度小於最大旋轉角度if(rotate < maxRotateAngle){float zoom = (float) ((rotate * 1.5) + maxZoom);camera.translate(0.0f, 0.0f, zoom);//設定圖片漸層效果child.setAlpha((int) (255 - rotate * 2.5));}//圖片向展示中心進行垂直角度旋轉camera.rotateY(rotateAngle);camera.getMatrix(imageMatrix);imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));imageMatrix.postTranslate(imageWidth / 2, imageHeight / 2);//還原映像變化的效果camera.restore();}

5)擷取Gallery展示圖片的中心點方法

具體實現代碼如下:

/** * 擷取Gallery展示圖片的中心點 * @return */public int getCurrentOfGallery(){return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2 + getPaddingLeft();}

6)擷取圖片中心點方法

具體實現代碼如下:

/** * 擷取圖片中心點 * @param view * @return */public int getCurrentOfView(View view){return view.getLeft() + view.getWidth() / 2;}

7)onSizeChanged方法

這個方法是當螢幕大小變化的時候,Android自動回調的方法,我在這個方法中的操作就是將擷取到的Gallery展示圖片的中心點賦值給成員變數currentOfGallery。

具體代碼如下:

@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {currentOfGallery = getCurrentOfGallery();super.onSizeChanged(w, h, oldw, oldh);}

8)完整代碼如下:

package com.lyz.gallery.activity;import android.content.Context;import android.graphics.Camera;import android.graphics.Matrix;import android.util.AttributeSet;import android.view.View;import android.view.animation.Transformation;import android.widget.Gallery;import android.widget.ImageView;/** * 自訂Gallery * @author liuyazhuang * */public class GalleryFlow extends Gallery {//最大的旋轉角度private int maxRotateAngle = 50;//最大縮放值private int maxZoom = -250;//記錄中間點的位置private int currentOfGallery;//建立相機對象private Camera camera = new Camera();public GalleryFlow(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);setStaticTransformationsEnabled(true);}public GalleryFlow(Context context, AttributeSet attrs) {super(context, attrs);//指定圖形是否變化 false:否  true:是setStaticTransformationsEnabled(true);}public GalleryFlow(Context context) {super(context);setStaticTransformationsEnabled(true);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {currentOfGallery = getCurrentOfGallery();super.onSizeChanged(w, h, oldw, oldh);}@Overrideprotected boolean getChildStaticTransformation(View child, Transformation t) {//得到圖片的中心點int currentOfChild = getCurrentOfView(child);int width = child.getLayoutParams().width;int height = child.getLayoutParams().height;//旋轉的角度int rotateAngle = 0;t.clear();//設定圖片變形樣式t.setTransformationType(Transformation.TYPE_MATRIX);//位置中心點位置if(currentOfChild == currentOfGallery){transformationBitmap((ImageView)child, t, 0);}else{//不是中心位置rotateAngle = (int) ((float)(currentOfGallery - currentOfChild) / width * maxRotateAngle);if(Math.abs(rotateAngle) > maxRotateAngle){rotateAngle = rotateAngle < 0 ? -maxRotateAngle : maxRotateAngle;}//圖片變形transformationBitmap((ImageView)child, t, rotateAngle);}return true;}/** * 圖片變形 * @param child * @param t * @param i */private void transformationBitmap(ImageView child, Transformation t, int rotateAngle) {//儲存映像變化的效果camera.save();Matrix imageMatrix = t.getMatrix();int rotate = Math.abs(rotateAngle);int imageWidth = child.getWidth();int imageHeight = child.getHeight();//z:正數:圖片變大//x:水平移動//y:垂直移動camera.translate(0.0f, 0.0f, 100.0f);//當前旋轉角度小於最大旋轉角度if(rotate < maxRotateAngle){float zoom = (float) ((rotate * 1.5) + maxZoom);camera.translate(0.0f, 0.0f, zoom);//設定圖片漸層效果child.setAlpha((int) (255 - rotate * 2.5));}//圖片向展示中心進行垂直角度旋轉camera.rotateY(rotateAngle);camera.getMatrix(imageMatrix);imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));imageMatrix.postTranslate(imageWidth / 2, imageHeight / 2);//還原映像變化的效果camera.restore();}/** * 擷取Gallery展示圖片的中心點 * @return */public int getCurrentOfGallery(){return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2 + getPaddingLeft();}/** * 擷取圖片中心點 * @param view * @return */public int getCurrentOfView(View view){return view.getLeft() + view.getWidth() / 2;}}

3、MainActivity

這個類主要實現的功能是載入布局檔案,構造要顯示的圖片的id數組,調用ImageAdapter方法實現圖片的顯示操作。

具體實現的代碼如下:

package com.lyz.gallery.activity;import android.os.Bundle;import android.app.Activity;import android.view.Menu;/** * 程式主入口 * @author liuyazhuang * */public class MainActivity extends Activity {private GalleryFlow gallery_flow;//存放圖片id的數組private int[] imageIds;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//構造存放圖片id的數組imageIds = new int[]{R.drawable.photo1,R.drawable.photo2,R.drawable.photo3,R.drawable.photo4,R.drawable.photo5,R.drawable.photo6,R.drawable.photo7,R.drawable.photo8};gallery_flow = (GalleryFlow) findViewById(R.id.gallery_flow);//執行個體化ImageAdapter對象ImageAdapter adapter = new ImageAdapter(this, imageIds);//向圖片數組中載入圖片adapter.createRefectedBitmap();gallery_flow.setAdapter(adapter);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}}

4、布局檔案activity_main.xml

這個布局檔案很簡單,就是放置了一個我們自己定義的GalleryFlow控制項。

具體實現代碼如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="@android:color/black">    <com.lyz.gallery.activity.GalleryFlow        android:id="@+id/gallery_flow"        android:layout_width="match_parent"        android:layout_height="match_parent"/></RelativeLayout>

5、AndroidManifest.xml

這個檔案中沒有做任何操作,都是Android自動產生的內容。

具體實現代碼如下:

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.lyz.gallery.activity"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk        android:minSdkVersion="8"        android:targetSdkVersion="18" />    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <activity            android:name="com.lyz.gallery.activity.MainActivity"            android:label="@string/app_name" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application></manifest>

三、運行效果


四、溫馨提示

大家可以到連結http://download.csdn.net/detail/l1028386804/9058447下載Android實現3D圖片瀏覽效果樣本完整原始碼

本執行個體中,為了方面,我把一些文字直接寫在了布局檔案中和相關的類中,大家在真實的項目中要把這些文字寫在string.xml檔案中,在外部參考這些資源,切記,這是作為一個Android程式員最基本的開發常識和規範,我在這裡只是為了方便直接寫在了類和布局檔案中。

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.