3D畫廊java
以前我都是寫的學習的內容,我在寫這些教程時遇到有趣的炫酷的小例子也會專門拿出來寫一篇文章,今天就寫一個酷炫的小例子,叫3D畫廊,它是屬於ViewPage的進階版。android
此項目下載地點:github.com/qySvip/3D-g…git
下面的指示器是使用的一大神的第三方庫,會在文章下方簡單講述一下。github
效果圖面試
3D畫廊的實現性能優化
首先是佈局文件bash
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:clipChildren="false"
android:background="@android:color/black"
android:id="@+id/frame_layout">
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="450dp"
android:layout_gravity="center"
android:id="@+id/gallery"
android:clipChildren="false"
android:layout_marginLeft="85dp"
android:layout_marginRight="85dp" />
<com.lwj.widget.viewpagerindicator.ViewPagerIndicator
android:id="@+id/indicator_circle_line"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_gravity="bottom"
android:background="#efefef"
app:vpi_default_color="#FF239AF5"
app:vpi_distance="60dp"
app:vpi_distanceType="BY_LAYOUT"
app:vpi_indicatorType="CIRCLE_LINE"
app:vpi_radius="10dp"
app:vpi_selected_color="#FF239AF5"
/>
</FrameLayout>
複製代碼
代碼中的ViewPagerIndicator是用於實現下方的指示器,這個咱們在最後在進行解釋;架構
首先佈局使用幀佈局,內部用到ViewPager控件,注意在ViewPager控件的父佈局中咱們要添加android:clipChildren="false"屬性,它的做用是定義它的子控件是否要在它應有的邊界內進行繪製,默認值爲true。咱們這裏要用false。app
而後在ViewPager中用到android:layout_marginLeft和android:layout_marginRight屬性,值不能太大,過大會致使看不到兩邊的圖像,具體根據本身滿意進行調整。高度屬性爲圖片和倒影的加起來的高度,本身進行調整。maven
GalleryPageTransformer類
package sample.sdk.qy.com.demo;
import android.support.v4.view.ViewPager;
import android.view.View;
public class GalleryPageTransformer implements ViewPager.PageTransformer {
private static final float MAX_ROTATION=20.0f;
private static final float MIN_SCALE=0.75f;
private static final float MAX_TRANSLATE=20.0f;
@Override
public void transformPage(View page, float position) {
if(position<-1) {
page.setTranslationX(MAX_TRANSLATE);
page.setScaleX(MIN_SCALE);
page.setScaleY(MIN_SCALE);
page.setRotationY(-MAX_ROTATION);
}
else if(position<=0) {
page.setTranslationX(-MAX_TRANSLATE*position);
float scale=MIN_SCALE+(1-MIN_SCALE)*(1.0f+position);
page.setScaleX(scale);
page.setScaleY(scale);
page.setRotationY(MAX_ROTATION*position);
}
else if(position<=1) {
page.setTranslationX(-MAX_TRANSLATE*position);
float scale=MIN_SCALE+(1-MIN_SCALE)*(1.0f-position);
page.setScaleX(scale);
page.setScaleY(scale);
page.setRotationY(MAX_ROTATION*position);
}
else {
page.setTranslationX(-MAX_TRANSLATE);
page.setScaleX(MIN_SCALE);
page.setScaleY(MIN_SCALE);
page.setRotationY(MAX_ROTATION);
}
}
}
複製代碼
PageTransformer是ViewPager內部定義的接口,這個接口主要用於控制ViewPager中item view的滑動效果。
package sample.sdk.qy.com.demo;
import android.content.Context;
import android.graphics.Bitmap;
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;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader;
public class ImageUtils {
public static Bitmap getReverseBitmapById(Context context, int resId, float percent) {
// get the source bitmap
Bitmap srcBitmap= BitmapFactory.decodeResource(context.getResources(), resId);
// get the tow third segment of the reverse bitmap
Matrix matrix=new Matrix();
matrix.setScale(1, -1);
Bitmap rvsBitmap=Bitmap.createBitmap(srcBitmap, 0, (int) (srcBitmap.getHeight()*(1-percent)),
srcBitmap.getWidth(), (int) (srcBitmap.getHeight()*percent), matrix, false);
// combine the source bitmap and the reverse bitmap
Bitmap comBitmap=Bitmap.createBitmap(srcBitmap.getWidth(),
srcBitmap.getHeight()+rvsBitmap.getHeight()+20, srcBitmap.getConfig());
Canvas gCanvas=new Canvas(comBitmap);
gCanvas.drawBitmap(srcBitmap, 0, 0, null);
gCanvas.drawBitmap(rvsBitmap, 0, srcBitmap.getHeight()+20, null);
Paint paint=new Paint();
LinearGradient shader=new LinearGradient(0, srcBitmap.getHeight()+20, 0, comBitmap.getHeight(),
Color.BLACK, Color.TRANSPARENT, Shader.TileMode.CLAMP);
paint.setShader(shader);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
gCanvas.drawRect(0, srcBitmap.getHeight()+20, srcBitmap.getWidth(), comBitmap.getHeight(), paint);
return comBitmap;
}
}
複製代碼
這是作圖片倒影的方法,內部使用了Canvas和Bitmap類,這些後面會進行講述。
package sample.sdk.qy.com.demo;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
public class ViewAdapter extends PagerAdapter {
private List<View> datas;
public ViewAdapter(List<View> list) {
datas=list;
}
@Override
public int getCount() {
return datas.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view==object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
View view=datas.get(position);
container.addView(view);
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(datas.get(position));
}
}
複製代碼
適配器類,這裏的適配方式爲圖片和倒影一同進行適配。
MainActivity類
package sample.sdk.qy.com.demo;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.lwj.widget.viewpagerindicator.ViewPagerIndicator;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity {
private List<View> pages;
private FrameLayout layout;
private ViewPager pager;
private ViewPagerIndicator mIndicatorCircleLine;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pages=getPages();
pager=(ViewPager) findViewById(R.id.gallery);
PagerAdapter adapter=new ViewAdapter(pages);
pager.setAdapter(adapter);
pager.setPageMargin(20);
pager.setOffscreenPageLimit(3);
pager.setPageTransformer(true, new GalleryPageTransformer());
layout=(FrameLayout) findViewById(R.id.frame_layout);
layout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return pager.dispatchTouchEvent(event);
}
});
mIndicatorCircleLine = (ViewPagerIndicator) findViewById(R.id.indicator_circle_line);
mIndicatorCircleLine.setViewPager(pager,9);
}
private List<View> getPages() {
List<View> pages=new ArrayList<>();
Field[] fields=R.drawable.class.getDeclaredFields();
try {
for (Field field : fields) {
if (field.getName().startsWith("page")) {
ImageView view = new ImageView(this);
view.setImageBitmap(ImageUtils.getReverseBitmapById(this, field.getInt(null), 0.5f));
pages.add(view);
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return pages;
}
}
複製代碼
主界面方法,主要用於填充入圖片、適配器適配。這裏填充圖片的方法爲在drawable文件中查找以page開頭的圖片進行填充。
到這裏3D畫廊就完成了。。。。。。。。。
指示器
下面來講一下指示器的作法,用的是網上一大神的第三方類。
使用方法:
一、在 project的build.gradle 添加:
allprojects { repositories { ... maven { url "https://jitpack.io" } } }
dependencies {
implementation 'com.github.LinweiJ:ViewPagerIndicator:0.1.0' }
注意這裏要用implementation,compile如今已被廢棄,官方顯示將在2018年年末刪除。
三、將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:關閉動畫)四、在java文件中初始化該控件
使用mIndicatorCircleLine.setViewPager(pager,9);,第一個參數爲適配器,第二個參數爲圖片的個數。