zoukankan      html  css  js  c++  java
  • 3D画廊

    3D画廊

    之前我都是写的学习的内容,我在写这些教程时遇到有趣的炫酷的小例子也会专门拿出来写一篇文章,今天就写一个酷炫的小例子,叫3D画廊,它是属于ViewPage的进阶版。

    此项目下载地点:https://github.com/qySvip/3D-gallery

    下面的指示器是使用的一大神的第三方库,会在文章下方简单讲述一下。

    效果图

    3D画廊的实现

    首先是布局文件

     1 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2     android:layout_width="match_parent"
     3     android:layout_height="match_parent"
     4     xmlns:app="http://schemas.android.com/apk/res-auto"
     5     android:clipChildren="false"
     6     android:background="@android:color/black"
     7     android:id="@+id/frame_layout">
     8 
     9     <android.support.v4.view.ViewPager
    10         android:layout_width="match_parent"
    11         android:layout_height="450dp"
    12         android:layout_gravity="center"
    13         android:id="@+id/gallery"
    14         android:clipChildren="false"
    15         android:layout_marginLeft="85dp"
    16         android:layout_marginRight="85dp" />
    17 
    18         <com.lwj.widget.viewpagerindicator.ViewPagerIndicator
    19             android:id="@+id/indicator_circle_line"
    20             android:layout_width="match_parent"
    21             android:layout_height="50dp"
    22             android:layout_gravity="bottom"
    23             android:background="#efefef"
    24             app:vpi_default_color="#FF239AF5"
    25             app:vpi_distance="60dp"
    26             app:vpi_distanceType="BY_LAYOUT"
    27             app:vpi_indicatorType="CIRCLE_LINE"
    28             app:vpi_radius="10dp"
    29             app:vpi_selected_color="#FF239AF5"
    30             />
    31 
    32 </FrameLayout>

    代码中的ViewPagerIndicator是用于实现下方的指示器,这个我们在最后在进行解释;

    首先布局使用帧布局,内部用到ViewPager控件,注意在ViewPager控件的父布局中我们要添加android:clipChildren="false"属性,它的作用是定义它的子控件是否要在它应有的边界内进行绘制,默认值为true。我们这里要用false。

    然后在ViewPager中用到android:layout_marginLeft和android:layout_marginRight属性,值不能太大,过大会导致看不到两边的图像,具体根据自己满意进行调整。高度属性为图片和倒影的加起来的高度,自己进行调整。

    GalleryPageTransformer类

     1 package sample.sdk.qy.com.demo;
     2 
     3 import android.support.v4.view.ViewPager;
     4 import android.view.View;
     5 
     6 public class GalleryPageTransformer implements ViewPager.PageTransformer {
     7     private static final float MAX_ROTATION=20.0f;
     8     private static final float MIN_SCALE=0.75f;
     9     private static final float MAX_TRANSLATE=20.0f;
    10 
    11     @Override
    12     public void transformPage(View page, float position) {
    13         if(position<-1) {
    14             page.setTranslationX(MAX_TRANSLATE);
    15             page.setScaleX(MIN_SCALE);
    16             page.setScaleY(MIN_SCALE);
    17             page.setRotationY(-MAX_ROTATION);
    18         }
    19         else if(position<=0) {
    20             page.setTranslationX(-MAX_TRANSLATE*position);
    21             float scale=MIN_SCALE+(1-MIN_SCALE)*(1.0f+position);
    22             page.setScaleX(scale);
    23             page.setScaleY(scale);
    24             page.setRotationY(MAX_ROTATION*position);
    25         }
    26         else if(position<=1) {
    27             page.setTranslationX(-MAX_TRANSLATE*position);
    28             float scale=MIN_SCALE+(1-MIN_SCALE)*(1.0f-position);
    29             page.setScaleX(scale);
    30             page.setScaleY(scale);
    31             page.setRotationY(MAX_ROTATION*position);
    32         }
    33         else {
    34             page.setTranslationX(-MAX_TRANSLATE);
    35             page.setScaleX(MIN_SCALE);
    36             page.setScaleY(MIN_SCALE);
    37             page.setRotationY(MAX_ROTATION);
    38         }
    39     }
    40 }

    PageTransformer是ViewPager内部定义的接口,这个接口主要用于控制ViewPager中item view的滑动效果。

    • setTranslationX     设置view相对原始位置的水平偏移量
    • setScaleX              设置水平缩放的基准点
    • setScaleY              设置竖直缩放的基准点
    • setRotationY          设置竖直的选择的基准点

     ImageUtils类

     1 package sample.sdk.qy.com.demo;
     2 
     3 import android.content.Context;
     4 import android.graphics.Bitmap;
     5 import android.graphics.BitmapFactory;
     6 import android.graphics.Canvas;
     7 import android.graphics.Color;
     8 import android.graphics.LinearGradient;
     9 import android.graphics.Matrix;
    10 import android.graphics.Paint;
    11 import android.graphics.PorterDuff;
    12 import android.graphics.PorterDuffXfermode;
    13 import android.graphics.Shader;
    14 
    15 public class ImageUtils {
    16     public static Bitmap getReverseBitmapById(Context context, int resId, float percent) {
    17         // get the source bitmap
    18         Bitmap srcBitmap= BitmapFactory.decodeResource(context.getResources(), resId);
    19         // get the tow third segment of the reverse bitmap
    20         Matrix matrix=new Matrix();
    21         matrix.setScale(1, -1);
    22         Bitmap rvsBitmap=Bitmap.createBitmap(srcBitmap, 0, (int) (srcBitmap.getHeight()*(1-percent)),
    23                 srcBitmap.getWidth(), (int) (srcBitmap.getHeight()*percent), matrix, false);
    24         // combine the source bitmap and the reverse bitmap
    25         Bitmap comBitmap=Bitmap.createBitmap(srcBitmap.getWidth(),
    26                 srcBitmap.getHeight()+rvsBitmap.getHeight()+20, srcBitmap.getConfig());
    27         Canvas gCanvas=new Canvas(comBitmap);
    28         gCanvas.drawBitmap(srcBitmap, 0, 0, null);
    29         gCanvas.drawBitmap(rvsBitmap, 0, srcBitmap.getHeight()+20, null);
    30         Paint paint=new Paint();
    31         LinearGradient shader=new LinearGradient(0, srcBitmap.getHeight()+20, 0, comBitmap.getHeight(),
    32                 Color.BLACK, Color.TRANSPARENT, Shader.TileMode.CLAMP);
    33         paint.setShader(shader);
    34         paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
    35         gCanvas.drawRect(0, srcBitmap.getHeight()+20, srcBitmap.getWidth(), comBitmap.getHeight(), paint);
    36         return comBitmap;
    37     }
    38 }

    这是做图片倒影的方法,内部使用了Canvas和Bitmap类,这些后面会进行讲述。

     ViewAdapter类

     1 package sample.sdk.qy.com.demo;
     2 
     3 import android.support.v4.view.PagerAdapter;
     4 import android.view.View;
     5 import android.view.ViewGroup;
     6 
     7 import java.util.List;
     8 
     9 public class ViewAdapter extends PagerAdapter {
    10     private List<View> datas;
    11 
    12     public ViewAdapter(List<View> list) {
    13         datas=list;
    14     }
    15 
    16     @Override
    17     public int getCount() {
    18         return datas.size();
    19     }
    20 
    21     @Override
    22     public boolean isViewFromObject(View view, Object object) {
    23         return view==object;
    24     }
    25 
    26     @Override
    27     public Object instantiateItem(ViewGroup container, int position) {
    28         View view=datas.get(position);
    29         container.addView(view);
    30         return view;
    31     }
    32 
    33     @Override
    34     public void destroyItem(ViewGroup container, int position, Object object) {
    35         container.removeView(datas.get(position));
    36     }
    37 }

    适配器类,这里的适配方式为图片和倒影一同进行适配。

    MainActivity类

     1 package sample.sdk.qy.com.demo;
     2 
     3 import android.app.Activity;
     4 import android.os.Bundle;
     5 import android.support.v4.view.PagerAdapter;
     6 import android.support.v4.view.ViewPager;
     7 import android.view.MotionEvent;
     8 import android.view.View;
     9 import android.widget.FrameLayout;
    10 import android.widget.ImageView;
    11 
    12 import com.lwj.widget.viewpagerindicator.ViewPagerIndicator;
    13 
    14 import java.lang.reflect.Field;
    15 import java.util.ArrayList;
    16 import java.util.List;
    17 
    18 public class MainActivity extends Activity {
    19 
    20     private List<View> pages;
    21     private FrameLayout layout;
    22     private ViewPager pager;
    23     private ViewPagerIndicator mIndicatorCircleLine;
    24 
    25     @Override
    26     protected void onCreate(Bundle savedInstanceState) {
    27         super.onCreate(savedInstanceState);
    28         setContentView(R.layout.activity_main);
    29 
    30         pages=getPages();
    31         pager=(ViewPager) findViewById(R.id.gallery);
    32         PagerAdapter adapter=new ViewAdapter(pages);
    33         pager.setAdapter(adapter);
    34         pager.setPageMargin(20);
    35         pager.setOffscreenPageLimit(3);
    36         pager.setPageTransformer(true, new GalleryPageTransformer());
    37 
    38         layout=(FrameLayout) findViewById(R.id.frame_layout);
    39         layout.setOnTouchListener(new View.OnTouchListener() {
    40             @Override
    41             public boolean onTouch(View v, MotionEvent event) {
    42                 return pager.dispatchTouchEvent(event);
    43             }
    44         });
    45 
    46         mIndicatorCircleLine = (ViewPagerIndicator) findViewById(R.id.indicator_circle_line);
    47         mIndicatorCircleLine.setViewPager(pager,9);
    48     }
    49 
    50     private List<View> getPages() {
    51         List<View> pages=new ArrayList<>();
    52         Field[] fields=R.drawable.class.getDeclaredFields();
    53         try {
    54             for (Field field : fields) {
    55                 if (field.getName().startsWith("page")) {
    56                     ImageView view = new ImageView(this);
    57                     view.setImageBitmap(ImageUtils.getReverseBitmapById(this, field.getInt(null), 0.5f));
    58                     pages.add(view);
    59                 }
    60             }
    61         } catch (IllegalAccessException e) {
    62             e.printStackTrace();
    63         }
    64         return pages;
    65     }
    66 }

    主界面方法,主要用于填充入图片、适配器适配。这里填充图片的方法为在drawable文件中查找以page开头的图片进行填充。

    到这里3D画廊就完成了。。。。。。。。。

    指示器

    下面来说一下指示器的做法,用的是网上一大神的第三方类。

    使用方法:

    1、在 project的build.gradle 添加:

    allprojects { repositories { ... maven { url "https://jitpack.io" } } }

    2、在module的build.gradle 添加:

    dependencies { implementation  'com.github.LinweiJ:ViewPagerIndicator:0.1.0' }

    注意这里要用implementation,compile现在已被废弃,官方显示将在2018年年底删除。

     3、将ViewPagerIndicator控件添加到布局文件。

    属性:

    • app:vpi_selected_color
    • app:vpi_default_color (如果 indicatorType=CIRCLE_LINE default_color 为指示器唯一颜色 ,selected_color 不起作用)
    • app:vpi_radius (点的大小,在indicatorType= CIRCLE_LINE 的情况下 radius 是点的高)
    • app:vpi_length (只作用在 indicatorType=CIRCLE_LINE 的情况下,为 指示器点的长度)
    • app:vpi_distance (只作用在 distanceType=BY_DISTANCE 的情况下)
    • app:vpi_num
    • app:vpi_indicatorType (LINE; CIRCLE; CIRCLE_LINE; BEZIER;SPRING)LINE:线 ; CIRCLE:圆点(默认) ; CIRCLE_LINE:圆角矩形; BEZIER:弹性球 ; SPRING: 弹簧粘性球
    • app:vpi_distanceType (BY_RADIUS; BY_DISTANCE ; BY_LAYOUT )BY_RADIUS:3倍radius ; BY_DISTANCE :定义固定距离 ;BY_LAYOUT :根据layout_width均分得到距离
    • app:vpi_animation(默认为true:动画开启 ; false:关闭动画)

     4、在java文件中初始化该控件

    使用mIndicatorCircleLine.setViewPager(pager,9);,第一个参数为适配器,第二个参数为图片的个数。

  • 相关阅读:
    每日英语:5 Ways the World Will Change Radically This Century
    每日英语:Foreign Visits Rise Amid Europe's Downturn
    vs2010和Matlab R2011b 混合编程的配置
    每日英语:Hon Hai Riot Underlines Rising Tensions in Chinese Factories
    优雅的实现对外接口,要注意哪些问题?
    一文搞定关系数据库设计要领,值得收藏!
    面试官:如果要存 IP 地址,用什么数据类型比较好?
    卧槽!IDEA 写代码防沉迷了?
    面试官:Minor GC、Major GC、Full GC 区别?我竟然答不上来。。
    Spring Boot + Vue + Shiro 实现前后端分离、权限控制
  • 原文地址:https://www.cnblogs.com/QY-admin/p/9969193.html
Copyright © 2011-2022 走看看