自訂Gallery控制項實現簡單3D圖片瀏覽器

來源:互聯網
上載者:User

標籤:圖片   matrix   imageview   3d   相簿   

本篇文章主要介紹如何使用自訂的Gallery控制項,實現3D效果的圖片瀏覽器的效果。

話不多說,先看效果。


上面是一個自訂的Gallery控制項,實現倒影和仿3D的效果,下面是一個圖片查看器,點擊上面的小圖片,可以在下面查看大圖片。

下面重點說一下,實現圖片查看器的思路。

1.手機中圖片路徑的擷取

首先,先不管圖片如何展示,如果我們想實現圖片查看器的功能,我們首先需要做的是擷取到所有的圖片的路徑資訊,只有這樣,我們才能實現對圖片的查看。

我們可以使用下面的代碼實現

private List<String> getImagesFromSD() {List<String> imageList = new ArrayList<String>();File f = Environment.getExternalStorageDirectory();if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {f = new File(Environment.getExternalStorageDirectory().toString());} else {Toast.makeText(MainActivity.this, R.string.sdcarderror, Toast.LENGTH_LONG).show();return imageList;}File[] files = f.listFiles();if (files == null || files.length == 0)return imageList;for (int i = 0; i < files.length; i++) {File file = files[i];if (isImageFile(file.getPath()))imageList.add(file.getPath());}return imageList;}

上面這個方法的作用,就是擷取SD卡中,所有檔案的尾碼名滿足圖片尾碼名的檔案的路徑,然後放到List容器中返回。

isImageFile方法是這樣實現的

private boolean isImageFile(String fName) {String end = fName.substring(fName.lastIndexOf(".") + 1, fName.length()).toLowerCase();if (end.equals("jpg") || end.equals("gif") || end.equals("png") || end.equals("jpeg") || end.equals("bmp")) {return true;}return false;}

2.上方小圖片3D效果展示的實現在完成了圖片路徑的擷取之後,我們下面要做的就是將圖片展示在上面的有3D效果的自訂Gallery控制項上面。現在版本中Gallery控制項已經不再推薦使用,取而代之的ViewPager和HorizonalScrollView控制項。下面介紹具有自訂Gallery控制項的實現

/** * 3D效果Gallery實現 *  * @time 2014年6月26日 下午9:10:47 */@SuppressWarnings("deprecation")public class GalleryFlow extends Gallery {private Camera mCamera = new Camera();// 兩側圖片最大旋轉角度private int mMaxRotationAngle = 60;private int mMaxZoom = -120;private int mCoveflowCenter;public GalleryFlow(Context context) {super(context);this.setStaticTransformationsEnabled(true);}public GalleryFlow(Context context, AttributeSet attrs) {super(context, attrs);this.setStaticTransformationsEnabled(true);}public GalleryFlow(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);this.setStaticTransformationsEnabled(true);}// 設定最大旋轉角public void setMaxRotationAngle(int maxRotationAngle) {mMaxRotationAngle = maxRotationAngle;}// 擷取當前控制項中心點x軸位置private int getCenterOfCoverflow() {return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2 + getPaddingLeft();}// 擷取view控制項的x軸位置private static int getCenterOfView(View view) {return view.getLeft() + view.getWidth() / 2;}// 預設傳回值是false,若設定城true,則每次gallery產生子控制項的時候,都會調用這個方法,所以我們可以將傳回值設定為true,然後完成child的旋轉等變形操作protected boolean getChildStaticTransformation(View child, Transformation t) {final int childCenter = getCenterOfView(child);final int childWidth = child.getWidth();int rotationAngle = 0;t.clear();t.setTransformationType(Transformation.TYPE_MATRIX);// 如果child控制項在中心位置,則不旋轉if (childCenter == mCoveflowCenter) {transformImageBitmap((ImageView) child, t, 0);} else {// 否則,將當前child控制項旋轉一定角度rotationAngle = (int) (((float) (mCoveflowCenter - childCenter) / childWidth) * mMaxRotationAngle);if (Math.abs(rotationAngle) > mMaxRotationAngle) {rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle : mMaxRotationAngle;}transformImageBitmap((ImageView) child, t, rotationAngle);}return true;}//重新計算控制項的x軸位置protected void onSizeChanged(int w, int h, int oldw, int oldh) {mCoveflowCenter = getCenterOfCoverflow();super.onSizeChanged(w, h, oldw, oldh);}// 將child控制項旋轉rotationAngle方法的實現private void transformImageBitmap(ImageView child, Transformation t, int rotationAngle) {mCamera.save();final Matrix imageMatrix = t.getMatrix();final int imageHeight = child.getLayoutParams().height;final int imageWidth = child.getLayoutParams().width;final int rotation = Math.abs(rotationAngle);// 在Z軸上正向移動camera的視角,實際效果為放大圖片。 如果在Y軸上移動,則圖片上下移動;X軸上對應圖片左右移動。mCamera.translate(0.0f, 0.0f, 100.0f);if (rotation < mMaxRotationAngle) {float zoomAmount = (float) (mMaxZoom + (rotation * 1.5));mCamera.translate(0.0f, 0.0f, zoomAmount);}// 在Y軸上旋轉,對應圖片豎向向裡翻轉。如果在X軸上旋轉,則對應圖片橫向向裡翻轉。mCamera.rotateY(rotationAngle);mCamera.getMatrix(imageMatrix);imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));imageMatrix.postTranslate((imageWidth / 2), (imageHeight / 2));// 恢複相機原狀態mCamera.restore();}}
通過自訂gallery控制項,現在我們已經實現了當滑動Gallery裡面的圖片時,兩側的圖片會發生一定角度的旋轉,也就是完成了3D效果的第一部,下一步,就需要我們在Gallery的Adapter裡面,對getView方法,進行改造,從而完成預覽小圖片的倒影效果
3.實現Adapter,完成倒影效果要完成倒映效果,我們需要在getView方法中,對穿進來的圖片進行處理,具體代碼如下
@SuppressWarnings({ "deprecation", "unused" })public class ImageAdapter extends BaseAdapter {private Context mContext;//用於存放圖片的路徑private List<String> imageFileList;//原始圖片private Bitmap originalImage;//反射的倒影圖片,高度為原始圖片一半private Bitmap reflectionImage;//用於存放處理後的整個圖片,高度為原始圖片的1.5倍private Bitmap bitmapWithReflection;//圖片的寬高private int width;private int height;//矩陣private Matrix matrix;//畫布private Canvas canvas;//原始映像與反射的倒影映像之間的間隔高度final int reflectionGap = 4;//用於getView返回private ImageView imageView;//倒影的陰影模糊效果private LinearGradient shader;public ImageAdapter(Context c, List<String> _imageFileList) { mContext = c;imageFileList = _imageFileList;matrix = new Matrix();//設定為x軸翻轉matrix.preScale(1, -1);}@Overridepublic int getCount() {return imageFileList.size();}@Overridepublic Object getItem(int position) {return position;}@Overridepublic long getItemId(int position) {return position;}//返回經過處理的ImageView對象@Overridepublic View getView(int position, View convertView, ViewGroup parent) {return createReflectedImages(imageFileList.get(position));}//這是最主要的方法,完成了對圖片的倒映效果處理public ImageView createReflectedImages(String filePath) {//擷取原始圖片originalImage = BitmapFactory.decodeFile(filePath);width = originalImage.getWidth();height = originalImage.getHeight();//建立倒影映像,高度是原始映像的一半,並且使用矩陣進行了x軸反轉,也就是倒影效果reflectionImage = Bitmap.createBitmap(originalImage, 0, height / 2, width, height / 2, matrix, false);//初始化Bitmap對象,用於存放處理後的圖片,高度為原始圖片的1.5倍bitmapWithReflection = Bitmap.createBitmap(width, (height + height / 2), Config.ARGB_8888);//根據bitmapWithReflection對象,建立一個畫布canvas = new Canvas(bitmapWithReflection);//先把原始映像畫上canvas.drawBitmap(originalImage, 0, 0, null);Paint paint = new Paint();//畫出原始映像與反射映像之間的小空隙,高度為reflectionGapcanvas.drawRect(0, height, width, height + reflectionGap, paint);//畫出倒影canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);//設定畫筆的陰影製作效果shader = new LinearGradient(0, originalImage.getHeight(), 0, bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff,TileMode.CLAMP);paint.setShader(shader);paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));//在倒影圖上用帶陰影的畫筆繪製矩形canvas.drawRect(0, height, width, bitmapWithReflection.getHeight() + reflectionGap, paint);//初始化一個ImageView對象imageView = new ImageView(mContext);//將處理後的映像設定為圖片資源imageView.setImageBitmap(bitmapWithReflection);imageView.setLayoutParams(new Gallery.LayoutParams(120, 160));imageView.setScaleType(ScaleType.CENTER_INSIDE);return imageView;}}

最主要的還是理解如何?的倒影效果。注釋應該是很詳細了,不過多解釋。4.如何使用自訂的Gallery控制項實現最終的圖片查看器下面,我們看一下,如何使用這個控制項,實現我們最終的效果。布局檔案
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:background="#F9F900"    android:gravity="center_horizontal"    android:orientation="vertical" >    <com.examole.gallery.GalleryFlow        android:id="@+id/mygallery"        android:layout_width="match_parent"        android:layout_height="100dp"        android:layout_marginTop="20dp"        android:gravity="center_vertical" />    <ImageSwitcher        android:id="@+id/switcher"        android:layout_width="wrap_content"        android:layout_height="match_parent"        android:layout_gravity="center_horizontal" /></LinearLayout>
我們在這裡使用了一個很陌生的類,那就是ImageSwicher,我們看一下,在Activity如何使用
public class MainActivity extends Activity implements AdapterView.OnItemSelectedListener, ViewSwitcher.ViewFactory {private List<String> ImageList;private ImageSwitcher mSwitcher;private Gallery gallery;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 擷取圖片路徑ImageList = getImagesFromSD();mSwitcher = (ImageSwitcher) findViewById(R.id.switcher);gallery = (Gallery) findViewById(R.id.mygallery);// ImageSwitcher控制項必須實現ViewSwitcher.ViewFactory介面,然後在makeView方法中,返回我們需要顯示的控制項即可mSwitcher.setFactory(this);// 設定圖片的進入和離開的動畫效果mSwitcher.setInAnimation(AnimationUtils.loadAnimation(this, android.R.anim.slide_in_left));mSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this, android.R.anim.slide_out_right));// 給gallery設定適配器gallery.setAdapter(new ImageAdapter(this, ImageList));gallery.setOnItemSelectedListener(this);}private List<String> getImagesFromSD() {List<String> imageList = new ArrayList<String>();File f = Environment.getExternalStorageDirectory();if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {f = new File(Environment.getExternalStorageDirectory().toString());} else {Toast.makeText(MainActivity.this, R.string.sdcarderror, Toast.LENGTH_LONG).show();return imageList;}File[] files = f.listFiles();if (files == null || files.length == 0)return imageList;for (int i = 0; i < files.length; i++) {File file = files[i];if (isImageFile(file.getPath()))imageList.add(file.getPath());}return imageList;}@SuppressLint("DefaultLocale")private boolean isImageFile(String fName) {String end = fName.substring(fName.lastIndexOf(".") + 1, fName.length()).toLowerCase();if (end.equals("jpg") || end.equals("gif") || end.equals("png") || end.equals("jpeg") || end.equals("bmp")) {return true;}return false;}@Overridepublic void onItemSelected(AdapterView<?> parent, View view, int position, long id) {// 當點擊上面的小圖片的時候,擷取圖片的絕對路徑,然後設定給mSwitcherString photoURL = ImageList.get(position);mSwitcher.setImageURI(Uri.parse(photoURL));}@Overridepublic void onNothingSelected(AdapterView<?> parent) {}@Overridepublic View makeView() {ImageView i = new ImageView(this);i.setBackgroundColor(0x00000000);i.setScaleType(ImageView.ScaleType.CENTER_INSIDE);i.setLayoutParams(new ImageSwitcher.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));return i;}}

除了ImageSwitcher這個控制項,其他的應該都很熟悉了,經過這幾個步驟,我們終於實現了一個簡單的仿3D效果的圖片查看器。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.