`
onewayonelife
  • 浏览: 259759 次
  • 性别: Icon_minigender_1
  • 来自: 太原
社区版块
存档分类
最新评论

Android 自定义Gallery

 
阅读更多

MainActivity

package org.wp.activity;

import android.app.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.Color;
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.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;

public class MainActivity extends Activity {
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		CoverFlow coverFlow = new CoverFlow(this);
		ImageAdapter imageAdapter = new ImageAdapter(this);
		imageAdapter.createReflectedImages();
		coverFlow.setAdapter(imageAdapter);

		coverFlow.setSpacing(-(int) convertDip2Pixel(this, 40));
		coverFlow.setSelection(2, true);
		coverFlow.setAnimationDuration(1000);
		coverFlow.setBackgroundColor(Color.WHITE);

		setContentView(coverFlow);
	}

	public class ImageAdapter extends BaseAdapter {
		private Integer[] mImageIds = { R.drawable.images1, R.drawable.images2,
				R.drawable.images3, R.drawable.images4, R.drawable.images5,
				R.drawable.images6, R.drawable.images7, R.drawable.images8,
				R.drawable.images9, R.drawable.images10 };

		private Context mContext;
		private ImageView[] mImages;

		public ImageAdapter(Context c) {
			mContext = c;
			mImages = new ImageView[mImageIds.length];
		}

		@Override
		public int getCount() {
			return Integer.MAX_VALUE;
		}

		@Override
		public Object getItem(int position) {
			return position;
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			return mImages[position % mImages.length];
		}

		public boolean createReflectedImages() {
			final int reflectionGap = 4;

			int index = 0;

			for (int imageId : mImageIds) {
				Bitmap originalBitmap = BitmapFactory.decodeStream(mContext
						.getResources().openRawResource(imageId));
				int width = originalBitmap.getWidth();
				int height = originalBitmap.getHeight();

				Matrix matrix = new Matrix();
				matrix.preScale(1, -1);

				Bitmap reflectionBitmap = Bitmap.createBitmap(originalBitmap,
						0, height * 7 / 8, width, height / 8, matrix, false);

				Bitmap withReflectionBitmap = Bitmap.createBitmap(width,
								(height + height / 8 + reflectionGap), Config.ARGB_8888);

				Canvas canvas = new Canvas(withReflectionBitmap);
				canvas.drawBitmap(originalBitmap, 0, 0, null);

				Paint defaultPaint = new Paint();
				canvas.drawRect(0, height, width, height + reflectionGap, defaultPaint);

				canvas.drawBitmap(reflectionBitmap, 0, height + reflectionGap, null);

				Paint paint = new Paint();
				LinearGradient shader = new LinearGradient(0, originalBitmap.getHeight(), 
						0, withReflectionBitmap.getHeight(), 0x70ffffff, 0x00ffffff, 
						TileMode.MIRROR);
				paint.setShader(shader);
				paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));

				canvas.drawRect(0, height, width, withReflectionBitmap.getHeight(), paint);

				ImageView imageView = new ImageView(mContext);
				imageView.setImageBitmap(withReflectionBitmap);
				imageView.setLayoutParams(new CoverFlow.LayoutParams(
						(int) convertDip2Pixel(mContext, 120),
						(int) convertDip2Pixel(mContext, 300)));
				imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
				// 消除图片移动过程中的锯齿
				BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
				drawable.setAntiAlias(true);

				mImages[index++] = imageView;
			}
			return true;
		}
	}

	public float convertDip2Pixel(Context context, int dip) {
		final float scale = context.getResources().getDisplayMetrics().density;
		float pixel = (int) (dip * scale + 0.5f);
		return pixel;
	}
}

 

CoverFlow

package org.wp.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;

/**
 * protected void setStaticTransformationsEnabled (boolean enabled)
 * 
 * When this property is set to true, this ViewGroup supports static
 * transformations on children;
 * 
 * this causes getChildStaticTransformation(View, android.view.animation.Transformation) 
 * to be invoked when a child is drawn.
 * 
 * Any subclass overriding getChildStaticTransformation(View,
 * android.view.animation.Transformation) should set this property to true.
 * 
 * (Gallery ==> AbsSpinner ==> AdapterView<T extends Adapter> ==> ViewGroup)
 */
public class CoverFlow extends Gallery {
	/** 视角 **/
	private Camera mCamera = new Camera();
	/** Child ImageView 最大的旋转角度 **/
	private int mMaxRotationAngle = 45;
	/** Center Child Z轴最大缩放距离 **/
	private int mMaxZoom = -120;
	/** Coverflow 的中心位置 **/
	private int mCoverflowCenter;
	/** 反转变量 **/
	private int lastPosition = 0;

	public CoverFlow(Context context) {
		super(context);
		this.setStaticTransformationsEnabled(true);
	}

	public CoverFlow(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.setStaticTransformationsEnabled(true);
	}

	public CoverFlow(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		this.setStaticTransformationsEnabled(true);
	}

	public int getmMaxRotationAngle() {
		return mMaxRotationAngle;
	}

	public void setmMaxRotationAngle(int mMaxRotationAngle) {
		this.mMaxRotationAngle = mMaxRotationAngle;
	}

	public int getmMaxZoom() {
		return mMaxZoom;
	}

	public void setmMaxZoom(int mMaxZoom) {
		this.mMaxZoom = mMaxZoom;
	}

	/** 获得CoverFlow的中心点 **/
	private int getCenterOfCoverflow() {
		return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2
				+ getPaddingLeft();
	}

	/** 获得指定View的中心点 **/
	private int getCenterOfView(View view) {
		return view.getLeft() + view.getWidth() / 2;
	}

	/**
	 * This method is called every time the widget changes size 
	 * e.g. when we change the orientation of the phone from portrait to landscape. 
	 * In the onSizeChanged method we just get the centre position 
	 * of the coverflow widget.
	 */
	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		mCoverflowCenter = getCenterOfCoverflow();
		super.onSizeChanged(w, h, oldw, oldh);
	}
	
	@Override
	protected int getChildDrawingOrder(int childCount, int i) {
		if (i == 0) lastPosition = 0;

		int centerPosition = getSelectedItemPosition()
				- getFirstVisiblePosition();

		// 当索引的位置是最后一个,返回中心点的child索引
		// 当索引的位置大于中心点child的索引,从右往左
		// 剩余的按正常顺序
		if (i == (childCount - 1)) {
			return centerPosition;
		} else if (i >= centerPosition) {
			lastPosition++;
			return childCount - lastPosition;
		} else {
			return i;
		}

	}

	@Override
	protected boolean getChildStaticTransformation(View child, Transformation t) {
		final int childCenter = getCenterOfView(child);
		final int childWidth = child.getWidth();
		int rotationAngle = 0;

		t.clear();
		// Indicates a transformation that applies a matrix only (alpha = 1.)
		t.setTransformationType(Transformation.TYPE_MATRIX);

		// 如果图片移动到中心点
		if (childCenter == mCoverflowCenter) {
			transformImageBitmap((ImageView) child, t, 0);
		} else {
			rotationAngle = (int) (((float) (mCoverflowCenter - childCenter) / childWidth) * mMaxRotationAngle);
			// 最大旋转角度不超过mMaxRotationAngle
			if (Math.abs(rotationAngle) > mMaxRotationAngle) {
				rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle : mMaxRotationAngle;
			}
			transformImageBitmap((ImageView) child, t, rotationAngle);
		}

		return true;
	}

	private void transformImageBitmap(ImageView child, Transformation t,
			int rotationAngle) {
		mCamera.save();
		final Matrix imageMatrix = t.getMatrix();
		final int imageWidth = child.getLayoutParams().width;
		final int imageHeight = child.getLayoutParams().height;
		final int rotation = Math.abs(rotationAngle);

		// 默认的缩小值
		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);
		}

		mCamera.rotateY(rotationAngle);
		mCamera.getMatrix(imageMatrix);

		imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));
		imageMatrix.postTranslate((imageWidth / 2), (imageHeight / 2));

		mCamera.restore();
	}
}

 

 

 

分享到:
评论

相关推荐

    android 自定义 gallery

    在Android开发中,有时我们可能需要自定义Gallery组件来满足特定的设计需求,因为原生的Gallery组件在某些情况下并不能提供完全符合我们预期的展示效果。本篇将详细讲解如何使用HorizontalScrollView来创建一个...

    android自定义gallery

    "android自定义gallery"项目就是一个很好的示例,它实现了左右滑动浏览图片的功能,并且带有当前选中图片位置的指示点,这种设计常见于应用启动时的向导页面。下面将详细介绍这个项目的知识点。 1. **自定义...

    Android自定义Gallery控件实现3D图片浏览器

    本篇文章主要介绍如何使用自定义的Gallery控件,实现3D效果的图片浏览器的效果。 话不多说,先看效果。 上面是一个自定义的Gallery控件,实现倒影和仿3D的效果,下面是一个图片查看器,点击上面的小图片,可以在...

    android自定义Gallery Demo实现随手滑动随停去掉两边空白

    接下来,为了测试和演示我们的自定义`Gallery`,我们可以创建一个简单的Android项目,包含一个主Activity和布局文件。在布局文件中,添加自定义的`MyGallery1`控件,并在Activity的`onCreate()`方法中设置数据源和...

    Android Gallery用法(自定义边框+底部小圆点)

    总的来说,自定义`Android Gallery`不仅提升了用户体验,还展示了Android开发中的灵活性。从自定义边框到动态的底部指示器,再到自动切换功能,这些都是提升用户界面交互性的重要手段。在实际开发中,我们应该根据...

    Android 使用Gallery_tabhost实现标签效果图源码.rar

    在Android开发中,`Gallery`和`TabHost`是两种常用的UI组件,它们可以用于创建丰富多样的用户界面。在这个项目中,`Android 使用Gallery_tabhost实现标签效果图源码.rar`是一个示例,展示了如何结合这两个组件来创建...

    Android自定义控件(3D画廊)

    这篇博客文章 "Android自定义控件(3D画廊)" 提供了一个实现这种效果的教程,下面将详细讲解相关知识点。 1. **自定义控件基础**:Android系统允许开发者创建自己的视图组件,通过继承现有的View或ViewGroup类,...

    android自定义3d画廊效果

    "android自定义3d画廊效果"是一个专为Android平台设计的特色功能,它通过实现3D视角的图片滚动效果,为用户提供了新颖且引人入胜的交互体验。这个3D Gallery效果的实现基于对Android系统的深入理解和熟练运用,主要...

    Android 自定义ListView + Gallery 组合

    在Android开发中,...总的来说,Android自定义ListView与Gallery组合的实现涉及到了数据绑定、视图复用、事件监听等多个核心知识点,通过熟练掌握这些技能,开发者可以构建出功能强大、用户体验优良的Android应用。

    Android 自定义RecyclerView 实现真正的Gallery效果程序源码

    本示例代码着重于如何通过自定义RecyclerView实现一个类似于Android原生Gallery的效果,即横向滑动浏览图片。Gallery组件在Android API 21(Lollipop)之后已被弃用,因此开发者需要寻找替代方案,例如使用...

    Android 自定义 HorizontalScrollView 替代Gallery

    原生的Android SDK提供了Gallery组件,但自Android 3.0(API级别11)起,Gallery已被弃用,推荐使用HorizontalScrollView或RecyclerView等替代品。本文将深入探讨如何使用自定义的HorizontalScrollView来实现类似...

    android 自定义gridView 按日期显示图片和视频 galleryDemo

    android 自定义gridView 按日期显示图片和视频 galleryDemo android 自定义gridView 按日期显示图片和视频 galleryDemo android 自定义gridView 按日期显示图片和视频 galleryDemo 免费下载 给个好评!

    Android 自定义 HorizontalScrollView 打造超强 Gallery效果 完整实例源码

    Android 自定义 HorizontalScrollView 打造超强 Gallery效果 完整实例源码 Android 自定义 HorizontalScrollView 打造超强 Gallery效果 完整实例源码 Android 自定义 HorizontalScrollView 打造超强 Gallery效果 ...

    Android 自定义ImageAdapter 图片左右滑动效果.rar

     实现的原理是 添加一ImageAdapter并设置给Gallery对象,设置一个itemclickListener并Toast被点击图片的位置,然后改写BaseAdapter自定义一ImageAdapter class ,创建ImageAdapter的构造器,取得Gallery属性的Index...

    Android Gallery自定义ImageView和Gallery实现图片浏览功能

    Android Gallery 自定义ImageView和Gallery实现图片浏览功能,类似Android图库软件,主要实现的功能有:图片左右滑动、放大缩小、放大弹回、缩小弹回。 一开始使用Viewpager实现图片浏览,发现两张图片滑动时没有...

    android gridView实现自定义gallery

    要使用GridView实现自定义Gallery功能,我们首先需要创建一个自定义的Adapter。Adapter是连接数据源和UI组件的关键,它负责将数据转化为视图并填充到GridView中。这里我们需要一个继承自BaseAdapter的自定义Adapter...

    Android自定义带倒影和偏转的超炫Gallery

    本文将详细探讨如何实现一个"Android自定义带倒影和偏转的超炫Gallery",该Gallery组件能展示出极具视觉冲击力的效果。 首先,让我们了解一下Android中的Gallery组件。Gallery是Android提供的一个特殊的视图,它...

    Android自定义横向列表GalleryImage完整app源码

    这个“Android自定义横向列表GalleryImage完整app源码”就是一个很好的示例,它提供了如何实现这样一个功能的具体代码。下面将详细解释相关知识点。 1. **自定义控件**: 自定义控件是Android开发中常见的一种技术...

Global site tag (gtag.js) - Google Analytics