本篇文章主要介紹如何使用自定義的Gallery控件,實現(xiàn)3D效果的圖片瀏覽器的效果。
創(chuàng)新互聯(lián)成立與2013年,先為巴宜等服務建站,巴宜等地企業(yè),進行企業(yè)商務咨詢服務。為巴宜企業(yè)網(wǎng)站制作PC+手機+微官網(wǎng)三網(wǎng)同步一站式服務解決您的所有建站問題。
話不多說,先看效果。

上面是一個自定義的Gallery控件,實現(xiàn)倒影和仿3D的效果,下面是一個圖片查看器,點擊上面的小圖片,可以在下面查看大圖片。
下面重點說一下,實現(xiàn)圖片查看器的思路。
1.手機中圖片路徑的獲取
首先,先不管圖片如何展示,如果我們想實現(xiàn)圖片查看器的功能,我們首先需要做的是獲取到所有的圖片的路徑信息,只有這樣,我們才能實現(xiàn)對圖片的查看。
我們可以使用下面的代碼實現(xiàn)
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方法是這樣實現(xiàn)的
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效果展示的實現(xiàn)
在完成了圖片路徑的獲取之后,我們下面要做的就是將圖片展示在上面的有3D效果的自定義Gallery控件上面。現(xiàn)在版本中Gallery控件已經(jīng)不再推薦使用,取而代之的ViewPager和HorizonalScrollView控件。
下面介紹具有自定義Gallery控件的實現(xiàn)
/**
* 3D效果Gallery實現(xiàn)
*
* @time 2014年6月26日 下午9:10:47
*/
@SuppressWarnings("deprecation")
public class GalleryFlow extends Gallery {
private Camera mCamera = new Camera();
// 兩側(cè)圖片最大旋轉(zhuǎn)角度
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);
}
// 設置最大旋轉(zhuǎn)角
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生成子控件的時候,都會調(diào)用這個方法,所以我們可以將返回值設置為true,然后完成child的旋轉(zhuǎn)等變形操作
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控件在中心位置,則不旋轉(zhuǎn)
if (childCenter == mCoveflowCenter) {
transformImageBitmap((ImageView) child, t, 0);
} else {
// 否則,將當前child控件旋轉(zhuǎn)一定角度
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控件旋轉(zhuǎn)rotationAngle方法的實現(xiàn)
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軸上旋轉(zhuǎn),對應圖片豎向向里翻轉(zhuǎn)。如果在X軸上旋轉(zhuǎn),則對應圖片橫向向里翻轉(zhuǎn)。
mCamera.rotateY(rotationAngle);
mCamera.getMatrix(imageMatrix);
imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));
imageMatrix.postTranslate((imageWidth / 2), (imageHeight / 2));
// 恢復相機原狀態(tài)
mCamera.restore();
}
}
通過自定義gallery控件,現(xiàn)在我們已經(jīng)實現(xiàn)了當滑動Gallery里面的圖片時,兩側(cè)的圖片會發(fā)生一定角度的旋轉(zhuǎn),也就是完成了3D效果的第一部,下一步,就需要我們在Gallery的Adapter里面,對getView方法,進行改造,從而完成預覽小圖片的倒影效果
3.實現(xiàn)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軸翻轉(zhuǎn)
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;
}
//返回經(jīng)過處理的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();
//創(chuàng)建倒影圖像,高度是原始圖像的一半,并且使用矩陣進行了x軸反轉(zhuǎn),也就是倒影效果
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);
//根據(jù)bitmapWithReflection對象,創(chuàng)建一個畫布
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;
}
}
最主要的還是理解如何實現(xiàn)的倒影效果。注釋應該是很詳細了,不過多解釋。
4.如何使用自定義的Gallery控件實現(xiàn)最終的圖片查看器
下面,我們看一下,如何使用這個控件,實現(xiàn)我們最終的效果。
布局文件
<?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控件必須實現(xiàn)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這個控件,其他的應該都很熟悉了,經(jīng)過這幾個步驟,我們終于實現(xiàn)了一個簡單的仿3D效果的圖片查看器。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。
分享文章:Android自定義Gallery控件實現(xiàn)3D圖片瀏覽器
URL地址:http://www.chinadenli.net/article28/iiisjp.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供、網(wǎng)站收錄、微信小程序、域名注冊、網(wǎng)站設計、網(wǎng)站設計公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)