zoukankan      html  css  js  c++  java
  • Android开发系列(七) Gallery 3D效果

      昨天没有做更新,原因是一直在看有关Gallery的内容,因为想做一个比较美观的图片浏览器,如果使用系统自带的Gallery类效果非常差,因此根据网上的总结,对Gallery类进行继承,进而对其中的效果进行自定义,可以实现比较美观的(伪)3D效果。下一节会把ImageSwitcher添加进来,进一步对图片浏览器优化。另外对网上牛人的帖子一并表示感谢。

    首先是布局文件:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="@android:color/background_dark" >
        
        <com.example.android_myowngallery.MyGallery 
            android:id="@+id/myGallery"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    
    </LinearLayout>

    注意这里因为对View控件进行了继承,所以控件的类型应该写成自己定义的那个类类名,否则还会出现ClassCastException

      然后是自己创建的MyGallery类

    package com.example.android_myowngallery;
    
    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;
    
    public class MyGallery extends Gallery{
    
    
        /**
         * 注意Gallery类有三个构造函数,在继承时必须要把这三个构造函数都继承过来,否则会有异常
         * @param context
         * @param attrs
         * @param defStyle
         */
        public MyGallery(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            // TODO Auto-generated constructor stub
        }
        
        public MyGallery(Context context, AttributeSet attrs) {
            super(context, attrs);
            // TODO Auto-generated constructor stub
        }
        
        public MyGallery(Context context) {
            super(context);
            // TODO Auto-generated constructor stub
        }
    
        
        /**
         * 覆写 getChildStaticTransformation方法,正是通过这个方法对Gallery的效果进行修改
         */
        @Override
        protected boolean getChildStaticTransformation(View child, Transformation t) {
            // TODO Auto-generated method stub
            //对转换信息初始化
            t.clear();
        
            //setTransformationType();
            //获得子控件(ImageView)偏移父控件偏移量 (用比例表示,在-1到1之间)
            float offSet=getOffSet(child);
            //根据偏移量,子控件,转换信息 进行效果设置
            tranformIamgeView(child, t, offSet); //不要忘记调用图像变换方法
            
            return true;
        }
        
        
        /**
         * 求出子控件偏移父控件中心的程度
         */
        //求出子控件的中心
        protected int getCenterOfChild(View view){
            
            return view.getLeft()+view.getWidth()/2;
            
            //这里的getLeft()是求出子控件左边界的横坐标,在加上一半宽度就是中心的横坐标了
            
        }
        
        protected int getCenterOfParent()
        {
            //有效宽度=宽度-左右边框
            //中心横坐标=左边框+有效宽度的一半
            return getPaddingLeft()+(getWidth()-getPaddingLeft()-getPaddingRight())/2;
        }
        
        protected float getOffSet(View view)
        {
            float cCenter=getCenterOfChild(view);
            float pCenter=getCenterOfParent();
            float offSet=(cCenter-pCenter)/pCenter;
            if(offSet<-1){
                offSet=-1;
            }
            else if(offSet>1){
                offSet=1;
            }
            return offSet;
        }
        
        
        /**
         * 该方法根据给定的参数进行修改图像的显示属性,实际上就是根据子控件偏移父控件中心的偏移量决定不同的显示
         * 效果,从而使图片的切换更加好看
         */
        protected void tranformIamgeView(View view, Transformation t, float offSet)
        {
            //这里创建一个Camera对象通过Camera类的translate方法改变“相机”的角度,进而使图片呈现不同的效果
            /**
             * android.graphics.Camera
             * 
             * @Camera.save();
             * @Camera.restore();  相机类的这两个方法需要同时出现
             */
            Camera mCamera=new Camera();
            /**
             * 通过Transformation对象获得一个Matrix对象,这个对象的方法用于对于图像坐标变换的属性进行设置
             * android.graphics.Matrix
             */
            Matrix matrix=t.getMatrix();
            mCamera.save();
            /**
             * z坐标为正时表示“相机”上升,意味着图像将变小,本例中打算将偏离父控件中心的View缩小,、
             * 所以z应该是正值
             */
            mCamera.translate(0, 0, Math.abs(offSet)*200);
            
            /****
             * ERROR!!
             * 
             * 
             * 将图片对象添加至矩阵中,这个方法必须再preTranslate的前面,否则对于变换中心的设置是无效的!!
             */
            mCamera.getMatrix(matrix);
            
            //先宽后高,关于这个方法的意义下文讨论
            
            matrix.preTranslate(-view.getMeasuredWidth()/2, -view.getMeasuredHeight()/2);
            matrix.postTranslate(view.getMeasuredWidth()/2, view.getMeasuredHeight()/2);
            
        
            
            mCamera.restore();  //将相机的状态保存
            
            //设置一下透明度Alpha,要注意这里的透明度是子控件ImageView的,如果透明度为0(不透明)
            //那么图片将不会显示,如果透明度为1,图片正常显示
            t.setAlpha(1-Math.abs(offSet));  
    
        }
        
    
    }

    这里matrix.preTranslate(-view.getWidth()/2, -view.getHeight()/2); 

    是指在矩阵变换之前把View向左上移动,也就是把矩阵变换的中心点由childView的原点(图片左上角)变成childView的中心点
          matrix.postTranslate(view.getWidth()/2, view.getWidth()/2);
    指在矩阵变换完之后,再把childView向右下方进行平移,移动到原来的位置(即屏幕的中心位置)

    另外注意  mCamera.getMatrix()方法应该放在preTranslate()方法前面!

      如同ListView一样,也要为Gallery设置适配器

    package com.example.android_myowngallery;
    
    import android.content.Context;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.ViewGroup.LayoutParams;
    import android.widget.BaseAdapter;
    import android.widget.Gallery;
    import android.widget.ImageView;
    
    public class MyAdapter extends BaseAdapter{
    
        private Context context;
        private int[] picRes;
        
        
        
        public MyAdapter(Context context, int[] picRes) {
            super();
            this.context = context;
            this.picRes = picRes;
        }
    
        @Override
        public int getCount() {
            // TODO Auto-generated method stub
            return picRes.length;
        }
    
        @Override
        public Object getItem(int position) {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public long getItemId(int position) {
            // TODO Auto-generated method stub
            return position;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            // TODO Auto-generated method stub
            /**
             * 说明:因为这里只有一个控件ImageView,所以为了简化代码在这里直接创建ImageView对象,
             * 在处理每一个GalleryItem中有多个控件时,还是要和ListView一样自定义每个Item的布局文件,
             * 一般自定义布局时才会使用LayoutInflater的inflate方法创建convertView,然后再进一步获得子控件的
             * ID,这里不用convertView,因为没有定义item的布局文件!
             */
            ImageView i=new ImageView(context);
                 //遗留问题:这里换成Gallery是否可以?感觉MyGallery还是最好!
            i.setLayoutParams(new MyGallery.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));       //这里必须要创建新对象!并且要使用父控件Gallery的内部类
            i.setImageResource(picRes[position]);
            return i;
        }
    
    }

    这里注意本适配器中不需要利用convertView ,只有当有子布局文件时才会通过inflate方法创建此view

    最后是MainActivity

    package com.example.android_myowngallery;
    
    import android.os.Bundle;
    import android.app.Activity;
    import android.view.Menu;
    import android.widget.Gallery;
    
    public class MainActivity extends Activity {
    
        
        protected int[] picRes={R.drawable.ew23,R.drawable.girl0,R.drawable.girl1,R.drawable.girl2,R.drawable.image01,
                R.drawable.image02,R.drawable.qwe2,R.drawable.w21};
        
        MyGallery g=null;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            g=(MyGallery)findViewById(R.id.myGallery);
            MyAdapter adapter=new MyAdapter(this,picRes);
            g.setAdapter(adapter);
        
        }
    
        
    
    }

    这里要创建 MyGallery对象

    最后附上一张结果图吧

  • 相关阅读:
    C语言之逻辑运算符
    iOS:实现图片的无限轮播---之使用第三方库SDCycleScrollView
    Mac 环境下svn服务器的配置
    ld: warning: directory not found for option 去掉警告的方法
    Mac怎么设置wifi热点
    如何获取AppStore软件安装包的路径
    四种卸载Mac软件的方法
    UIAlertController
    uiview关联xib
    OC学习篇之---文件的操作
  • 原文地址:https://www.cnblogs.com/carlos-vic/p/Carlos_V_Android_7.html
Copyright © 2011-2022 走看看