中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android自定義Gallery控件實現3D圖片瀏覽器

發布時間:2020-09-29 09:16:56 來源:腳本之家 閱讀:227 作者:趙凱強 欄目:移動開發

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

話不多說,先看效果。

Android自定義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); 
     
  } 
   
  @Override 
  public int getCount() { 
    return imageFileList.size(); 
  } 
 
  @Override 
  public Object getItem(int position) { 
    return position; 
  } 
 
  @Override 
  public long getItemId(int position) { 
    return position; 
  } 
 
  //返回經過處理的ImageView對象 
  @Override 
  public 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(); 
    //畫出原始圖像與反射圖像之間的小空隙,高度為reflectionGap 
    canvas.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; 
 
  @Override 
  public 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; 
 
  } 
 
  @Override 
  public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 
    // 當點擊上面的小圖片的時候,獲取圖片的絕對路徑,然后設置給mSwitcher 
    String photoURL = ImageList.get(position); 
    mSwitcher.setImageURI(Uri.parse(photoURL)); 
  } 
 
  @Override 
  public void onNothingSelected(AdapterView<?> parent) { 
 
  } 
 
  @Override 
  public 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效果的圖片查看器。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

哈尔滨市| 中西区| 湘西| 井冈山市| 永春县| 浦东新区| 商都县| 安宁市| 龙门县| 海林市| 清苑县| 永顺县| 常熟市| 盐源县| 锡林浩特市| 肃南| 桐柏县| 赤城县| 双桥区| 沧源| 冀州市| 凤城市| 抚松县| 建德市| 富裕县| 浮山县| 泾川县| 雷山县| 当阳市| 云梦县| 清水河县| 甘谷县| 海丰县| 南岸区| 乌苏市| 绥宁县| 建德市| 剑川县| 夏邑县| 西贡区| 克什克腾旗|