今天来跟大家分享一下立体电子相册的制作,主要方法是在Gallery的基础上重写它的展示方法等,使其有个更加立体化(炫酷)的展示。哈哈。效果图如下

今天的分享方式简单粗暴,做demo的时候注释写得很详细,就直接上代码了。

1.布局

<LinearLayout 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:orientation="vertical"tools:context=".MainActivity" ><TextView android:background="#888888"android:padding="20dp"android:id="@+id/tv_title"android:layout_width="match_parent"android:layout_height="wrap_content"android:textStyle="bold"android:textSize="18dp"android:text="娴娴的最爱"android:gravity="center"/><ImageView android:layout_gravity="center_horizontal"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:id="@+id/iv"/><cn.xianxian.demo.view.MyGalleryandroid:padding="20dp"android:id="@+id/gallery"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_alignParentLeft="true"android:background="#888888"/>
</LinearLayout>

2.自定义Gallery

package cn.xianxian.demo.view;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;/*** * 自定义MyGallery,呈现效果 前后图片的显示呈现一定的角度**/
public class MyGallery extends Gallery {// gallery的中心点private int galleryCenterPoint = 0; private Camera camera;public MyGallery(Context context, AttributeSet attrs) {super(context, attrs);// 启用getChildStaticTransformation被调用setStaticTransformationsEnabled(true);camera = new Camera();}/*** 当gallery控件的宽和高改变时回调此方法, 第一次计算出gallery的宽和高时, 也会出发此方法*/@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);galleryCenterPoint = getGalleryCenterPoint();}/*** 返回gallery的item的子图形变换效果 Transformation 指定当前item的变换效果*/@Overrideprotected boolean getChildStaticTransformation(View child, Transformation t) {// item的中心点int viewCenterPoint = getviewCenterPoint(child); // 默认旋转角度为0int rotateAngle = 0; // 如果当前的View的中心点不等于gallery的中心点, 就是两边的图片, 需要计算旋转角度if (viewCenterPoint != galleryCenterPoint) {// gallery中心点 - 图片中心点 = 差值int diff = galleryCenterPoint - viewCenterPoint;// 差值 / 图片的宽度 = 比值float scale = (float) diff / (float) child.getWidth();// 比值 * 最大旋转角度 = 最终的旋转角度rotateAngle = (int) (scale * 50);// 当前角度超过了50, 需要赋值到50 或者 -50if (Math.abs(rotateAngle) > 50) { rotateAngle = rotateAngle > 0 ? 50 : -50;}}// 设置变换效果之前, 需要把Transformation中的上一个item的变换效果清楚t.clear();// 设置变换效果的类型为矩阵类型t.setTransformationType(Transformation.TYPE_MATRIX); startTransformationItem((ImageView) child, rotateAngle, t);return true;}/*** 设置变换效果* * @param iv*            gallery的item* @param rotateAngle*            旋转的角度* @param t*            变换的对象*/private void startTransformationItem(ImageView iv, int rotateAngle,Transformation t) {// 保存状态camera.save(); // 取旋转角度的绝对值int absRotateAngle = Math.abs(rotateAngle);// 放大效果(中间的图片要比两边的图片要大)camera.translate(0, 0, 100f); // 给摄像机定位int zoom = -250 + (absRotateAngle * 2);camera.translate(0, 0, zoom);//透明度(中间的图片是完全显示, 两边有一定的透明度)int alpha = (int) (255 - (absRotateAngle * 2.5));iv.setAlpha(alpha); // 透明度取值范围: 0 ~ 255, 0 就是完全隐藏, 255 完全显示// 旋转(在中间的图片没有旋转角度, 只要不在中间就有旋转角度)camera.rotateY(rotateAngle);// 变换的矩阵, 需要把变换的效果添加到矩阵中Matrix matrix = t.getMatrix();// 给matrix赋值// 把matrix矩阵给camera对象,camera对象就会把上面添加的效果转换成矩阵添加到matrix对象中camera.getMatrix(matrix); // 矩阵前乘matrix.preTranslate(-iv.getWidth() / 2, -iv.getHeight() / 2);// 矩阵后乘matrix.postTranslate(iv.getWidth() / 2, iv.getHeight() / 2);// 恢复到之前保存的状态camera.restore(); }/*** 获得gallery的中心点*/private int getGalleryCenterPoint() {return this.getWidth() / 2;}/*** 获得view的中心点*/private int getviewCenterPoint(View v) {// 图片的宽度的一半 + 图片左边在父控件中的位置return v.getWidth() / 2 + v.getLeft(); }
}

3.自定义工具类,设置倒立阴影效果

package cn.xianxian.demo;import java.lang.ref.SoftReference;
import java.util.Hashtable;import android.content.res.Resources;
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.util.Log;public class ImageUtils {private static final String TAG = "ImageUtils";// 缓存集合private static Hashtable<Integer, SoftReference<Bitmap>> mCacheHashTable = new Hashtable<Integer, SoftReference<Bitmap>>();/*** 根据id返回一个处理后的图片(带有下面立体阴影效果的图片)*/public static Bitmap getImageBitmap(Resources res, int imageID) {// 先去集合中取当前imageID 是否已经拿过图片, 如果集合中有, 说明已经拿过, 直接使用集合中的图片返回SoftReference<Bitmap> softReference = mCacheHashTable.get(imageID);if (softReference != null) {Bitmap bitmap = softReference.get();if (bitmap != null) {// 从内存中取return bitmap;}}// 如果集合中没有, 就调用getInvertImage得到一个图片, 需要向集合中保留一张, 最后返回当前图片Bitmap invertImage = getInvertImage(res, imageID);// 在集合中存一份, 便于下次再取的时候直接去集合中取.mCacheHashTable.put(imageID, new SoftReference<Bitmap>(invertImage));return invertImage;}/*** 根据id返回一个处理后的图片*/public static Bitmap getInvertImage(Resources res, int imageID) {// 获取原图Bitmap sourceBitmap = BitmapFactory.decodeResource(res, imageID);// 生成倒影图片Matrix m = new Matrix(); // 图形矩阵m.setScale(1f, -1f); // 让图形按照矩阵进行垂直反转Bitmap invertBitmap = Bitmap.createBitmap(sourceBitmap, 0,sourceBitmap.getHeight()/2 , sourceBitmap.getWidth(),sourceBitmap.getHeight()/2, m, false);// 把两张图片合成一张Bitmap resultBitmap = Bitmap.createBitmap(sourceBitmap.getWidth(),(int) (sourceBitmap.getHeight() * 1.5 + 5), Config.ARGB_8888);Canvas canvas = new Canvas(resultBitmap); // 指定画板画在合成图片上canvas.drawBitmap(sourceBitmap, 0, 0, null); // 把原图画在合成图片的上面canvas.drawBitmap(invertBitmap, 0, sourceBitmap.getHeight() + 5, null); // 把倒影图片画在合成图片上// 添加遮罩效果Paint paint = new Paint();// 设置颜色LinearGradient shader = new LinearGradient(0,sourceBitmap.getHeight() + 5, 0, resultBitmap.getHeight(),0x70ffffff, 0x00ffffff, TileMode.CLAMP);paint.setShader(shader);// 设置模式为: 遮罩, 是取交集paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));canvas.drawRect(0, sourceBitmap.getHeight() + 5,sourceBitmap.getWidth(), resultBitmap.getHeight(), paint);return resultBitmap;}
}

4.主界面的加载,由于我这里是自动滑屏显示的,所以Adapter的getCount返回一个很大的值,大家可以根据需要自行修改(不需要自动播放,不要开启线程即可)

package cn.xianxian.demo;import java.util.Random;import cn.xianxian.demo.R.id;
import cn.xianxian.demo.view.MyGallery;
import android.R.integer;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Gallery.LayoutParams;
import android.widget.ImageView;public class MainActivity extends Activity {private MyGallery gallery;private TextView tv_title;private ImageView iv;//用于保存要保存图片的idprivate int[] pics;private int count;private boolean isCircle = true;//随机搭配一个颜色值private Random random;private int color, a, b, c;private Handler handler;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//初始化控件gallery = (MyGallery) findViewById(R.id.gallery);tv_title = (TextView) findViewById(R.id.tv_title);iv=(ImageView) findViewById(R.id.iv);pics = new int[] {R.drawable.pic001, R.drawable.pic002, R.drawable.pic003,R.drawable.pic004, R.drawable.pic005, R.drawable.pic006,R.drawable.pic007, R.drawable.pic008, R.drawable.pic000,R.drawable.pic009, R.drawable.pic010 };gallery.setAdapter(new MyAdapter());handler = new Handler(new InnerCallBack());random = new Random();new MyThread().start();}// 开启线程,实现图片的自动切换private class MyThread extends Thread {@Overridepublic void run() {//isCircle值用于控制其是否自动播放,可以在后期增加按钮,通过改变isCircle的值来控制播放效果while (isCircle) {try {sleep(2000);a = random.nextInt(255);b = random.nextInt(255);c = random.nextInt(255);color = Color.rgb(a, b, c);Message.obtain(handler).sendToTarget();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}super.run();}}// 消息机制,处理子线程更新界面问题private class InnerCallBack implements Handler.Callback {@Overridepublic boolean handleMessage(Message arg0) {//滑屏图片的实现gallery.setId(++count);gallery.onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, null);//顶部文字变色tv_title.setTextColor(color);iv.setImageResource(pics[count % pics.length]);return true;}}/*** * 自定义Adapter* */private class MyAdapter extends BaseAdapter {@Overridepublic int getCount() {return Integer.MAX_VALUE;}@Overridepublic Object getItem(int position) {return pics[position % pics.length];}@Overridepublic long getItemId(int position) {return position % pics.length;}@Overridepublic View getView(int position, View view, ViewGroup viewGroup) {ImageView iv = null;if (view == null) {iv = new ImageView(MainActivity.this);// 要把iv放入哪里,就导入哪个容器的LayoutParams的包LayoutParams params = new LayoutParams(300, 420);iv.setLayoutParams(params);} else {iv = (ImageView) view;}Bitmap bitmap = ImageUtils.getImageBitmap(MainActivity.this.getResources(), pics[position% pics.length]);BitmapDrawable bd = new BitmapDrawable(bitmap);bd.setAntiAlias(true); // 消除锯齿iv.setImageDrawable(bd);LayoutParams params = new LayoutParams(160, 240);iv.setLayoutParams(params);return iv;}}}

这样子就可以完成立体版的电子相册的展示了~

娴娴的话:不管过去的还是过不去的,日子总会继续,困难和笑脸都是生活。反正没有选择,反正都会结束,做自己该做的。只要你是对的,那你走的路也是对的,然后微笑着                     顺其自然。

Android端立体电子相册的制作相关推荐

  1. android收费知乎,知乎 Android 端的一次重设计练习

    文章为作者基于自己做知乎 Android 端重设计的总结分享,一起来看. 这次做知乎 Android 端重设计,是由于四个月前,Android 端去掉了顶部导航的蓝条.由于设计趋势种种缘由虽然可以理解 ...

  2. Android端恶意锁屏勒索应用分析

    一.前言 5月12日,一场全球性互联网灾难悄然而至,一款名为WannaCRY的PC端恶意勒索软件利用NSA泄漏的危险漏洞"永恒之蓝",给100多个国家和地区10万台电脑造成了巨大的 ...

  3. UI交互设计:红绿立体图片的制作

    UI交互设计:红绿立体图片的制作 文章目录 UI交互设计:红绿立体图片的制作 实验原理 python之openCV 实验流程 一.怎么拥有python(老鸟请跳过) 二.怎么安装openCV 三.写点 ...

  4. Android 端 2D 横屏动作冒险类闯关游戏【100010436】

    Android 端 2D 横屏动作冒险类闯关游戏 摘要 随着闯关类游戏的玩法与数目的不断增加,本文所设计的一款名为<Wander In Color>的动作冒险闯关类游戏,将从一个新的角度入 ...

  5. 图形引擎实战:手游Android端后台下载技术分享

    一.功能特点 手游android端后台下载SDK是畅游自主研发的一款移动平台android端后台文件下载工具包,它主要提供网络文件的后台下载功能,功能完善,性能高,可以满足游戏制作有关后台下载文件的需 ...

  6. android 程序 读logo,Android端APP更换logo和名称后都需要些测试哪些内容呢?

    原标题:Android端APP更换logo和名称后都需要些测试哪些内容呢? 之前有人在搜狗测试粉丝群中问过APP更换logo和名称后需要怎么测试呢?小编正好经历过这样的需求,下面来系统整理一下APP更 ...

  7. Android端WEEX + HTTPDNS 最佳实践

    由于WebView并未暴露处设置DNS的接口,因而在WebView场景下使用HttpDns存在很多无法限制,但如果接入WEEX,则可以较好地植入HTTPDNS,本文主要介绍在WEEX场景下接入HTTP ...

  8. JMessage Android 端开发详解

    JMessage Android 端开发详解 目前越来越多的应用会需要集成即时通讯功能,这里就为大家详细讲一下如何通过集成 JMessage 来为你的 App 增加即时通讯功能. 首先,一个最基础的 ...

  9. Android端调用Caffe模型实现CNN分类

    本文的主要内容如下. 移动端的深度学习的实现方式 tiny-cnn介绍以及移动端移植 总结与改进 应用截图 一.移动端深度学习的几种实现方式 (1)Caffe的移动端编译项目 caffe(命令式框架) ...

最新文章

  1. mybatis参数有list和实体类_Mybatis的几种传参方式,你了解吗?
  2. UBUNTU adb连接android设备
  3. 复习04统计学习方法(朴素贝叶斯算法Naive Bayes)---图片版
  4. 这么详细的Python matplotlib 绘制图形 还不赶紧收藏
  5. tableau必知必会之用蝴蝶图(旋风图)实现数据之间对比
  6. 重构:改善饿了么交易系统的设计思路
  7. 创建RMAN CATALOG
  8. tensorflow 读取cifar_对tensorflow中cifar-10文档的Read操作详解
  9. nodejs连接postgresql_PostgreSQL 使用 node-postgres 在 node.js 中的应用
  10. (转载)高光谱数据读取by multibandread函数
  11. 【专题】CSDN下载频道4月热门资源top100汇总
  12. 深入浅出设计模式---4、适配器模式
  13. echart 表格_市政工程表格不会填?市政工程1000个表格模板,一键即可套用
  14. mt2503 用Dct tool打开codegen.dws提示版本 不match
  15. python自回归_【时间序列】自回归模型
  16. 如何将多个图片合成一个pdf
  17. 评分卡实例:一步一步实现评分卡(详细长文)
  18. python开发跟淘宝有关联微_为什么微商和淘宝卖家不得不做公众号和小程序?
  19. 2553. 【NOIP2011模拟9.7】射命丸文 (Standard IO)
  20. 我那个工资3000的朋友,一年存了60万:聪明人从不靠死工资续命

热门文章

  1. stm32/gd32爱玛电动车控制器资料 电动车控制器原理图、PCB和程序
  2. 怎么把图片转换成excel?原来这么简单
  3. 区域医疗卫生平台建设(五) HL7 RIM
  4. 几十万台 Exchange 服务器已被入侵,Exchange Hafnium 修复补丁来了!
  5. python做公司网站_网站的建设_ 网站建设那个好_ _我要做个网站_Python语言,绘制彩虹场景...
  6. 图像识别(5)——《OpenCV3编程入门-毛星云》第三部分 掌握imgproc组件
  7. 最小生成树的克鲁斯卡尔算法
  8. 电脑通过一加手机USB共享手机的移动网络
  9. #python注释代码对吗,以下Python注释代码不正确的是()。A.()#()Python注释代码()B.()#Python...
  10. 关于波斯历(奇怪的历法)