实现效果图
viewpagerdemo.gif这个效果是用ViewPager
实现的,实现方式为ViewPager + Fragment + PageTransformer
。主要功能点有
-
ViewPager+Fragment
无限循环,ViewPager
的无限循环比较简单的有以ViewPager+View
的方式实现,这里使用ViewPager+Fragment
是因为Fragment
比View
有更多的方法,更多的属性,以及生命周期以便于灵活的、高效的完成开发任务 - 通过
PageTransformer
实现左右两张图片的显示及特效添加 - 动态修改
ViewPager
的滑动速度 - 动态控制
ViewPager
对连续长按遥控器左右键的事件响应
一、ViewPager+Fragment无限循环实现
无限循环功能点的实现主要工作在Adapter
中,通过覆写下面4个方法来实现功能
package com.hpplay.muiltythreaddemo.viewpagerdemo;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.view.ViewGroup;
import java.util.ArrayList;
/**
* Created by DON on 2016/12/30.
*/
public class ViewPagerAdapter extends FragmentPagerAdapter {
private ArrayList<Integer> dataBeanArrayList;
FragmentManager mFm;
public ViewPagerAdapter(FragmentManager fm, ArrayList<Integer> fragmentArrayList) {
super(fm);
this.mFm = fm;
this.dataBeanArrayList = fragmentArrayList;
}
@Override
public ItemPagerFragment getItem(int position) {
int realPosition = position % dataBeanArrayList.size();
ItemPagerFragment itemViewPagerFragment = new ItemPagerFragment();
itemViewPagerFragment.setData(dataBeanArrayList.get(realPosition));
return itemViewPagerFragment;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
ItemPagerFragment itemRecyclerViewPagerFragment = (ItemPagerFragment)
super.instantiateItem(container, position);
return itemRecyclerViewPagerFragment;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
@Override
public int getCount() {
return dataBeanArrayList.size() <= 1 ? dataBeanArrayList.size() : Integer.MAX_VALUE;
}
}
上面ItemPagerFragment
为ViewPager
内嵌的Fragment
,用于展示具体的图片。
新建类ViewPagerFragment
,实现ViewPager
代码
package com.hpplay.muiltythreaddemo.viewpagerdemo;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import com.hpplay.muiltythreaddemo.R;
import java.lang.reflect.Field;
import java.util.ArrayList;
/**
* Created by DON on 2017/7/24.
*/
public class ViewPagerFragment extends Fragment {
private ViewPager viewPager;
private ViewPagerAdapter pagerAdapter;
private ArrayList<Integer> dataBeanArrayList = new ArrayList<>();
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
return View.inflate(getActivity(), R.layout.f_viewpager, null);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
viewPager = (ViewPager) view.findViewById(R.id.viewPager);
int drawable[] = {R.drawable.im1, R.drawable.im2, R.drawable.im3, R.drawable.im4, R.drawable.im5};
for (int i = 0; i < drawable.length; i++) {
dataBeanArrayList.add(drawable[i]);
}
pagerAdapter = new ViewPagerAdapter(getActivity().getSupportFragmentManager()
, dataBeanArrayList);
viewPager.setAdapter(pagerAdapter);
viewPager.setPageTransformer(true, new PageTransformer());
viewPager.setOffscreenPageLimit(2);
viewPager.setFocusable(true);
viewPager.setFocusableInTouchMode(true);
if (dataBeanArrayList.size() > 1) {
int position = Integer.MAX_VALUE / 2;
while (position % dataBeanArrayList.size() > 0) {
++position;
}
viewPager.setCurrentItem(position);//保证ViewPager当前显示的是第一个数据
}
pagerAdapter.notifyDataSetChanged();
}
}
ItemPagerFragment
作为ViewPager
内嵌的Fragment
,实现如下
package com.hpplay.muiltythreaddemo.viewpagerdemo;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.hpplay.muiltythreaddemo.R;
/**
* Created by DON on 2016/12/30.
*/
public class ItemPagerFragment extends Fragment {
private int mDataBean;
private ImageView imageView;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
return View.inflate(getActivity(), R.layout.item_view_pager, null);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initView(view);
}
public void initView(View view) {
imageView = (ImageView) view.findViewById(R.id.viewpager_item_iv);
// imageView.setScaleType(ImageView.ScaleType.MATRIX);
Glide.with(getActivity())
.load(mDataBean)
.centerCrop()
.crossFade()
.into(imageView);
imageView.setFocusable(false);
imageView.setFocusableInTouchMode(false);
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
}
public void setData(int dataBean) {
this.mDataBean = dataBean;
}
}
这个类比较简单,只负责展示图片。但是如果要实现效果图中左右两张图片都要可见的效果,这里的布局文件就要稍作处理,用于显示图片的ImageView
不能全屏。
item_view_pager.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/viewpager_item_iv"
android:layout_width="400dp"
android:layout_height="180dp"
android:layout_centerInParent="true" />
</RelativeLayout>
ImageView
的父布局是全屏的,这个是没法改变的,如果想要在一个界面中显示ViewPager的三张内容,就先需要在这里把左右两张图片的位置给预留出来,然后通过PageTransformer
对左右两张图片做位移,使其能够在界面中显示出来。
二、通过PageTransformer
实现特效
package com.hpplay.muiltythreaddemo.viewpagerdemo;
import android.support.v4.view.ViewPager;
import android.view.View;
public class PageTransformer implements ViewPager.PageTransformer {
/**
* position会根据view的移动而变化 比如当前有三个view 1,2,3
* 2在中间的时候,那么view2的position 为 0;
* 1在左边的时候,那么view1 的position为 -1;
* 3在右边的时候 , 那么view3的position为1;
* <p>
* 所以在view2移动的view3 值得变化范围就是 0---1
* VIEW2移动的view1 值得变化范围是 0 --- -1
* 反之 1---0 , -1 --- 0
*
* @param page 移动的View对象
* @param position 移动位置变化的值
*/
@Override
public void transformPage(View page, float position) {
int rorate = (int) (30 + (position - 1) * 30);
//根据position设置界面上三张图片的旋转角度,实现左右两张图片倾斜的特效
page.setRotationY(rorate);
float scale = (float) Math.max(1 - Math.abs(position), 0.74);
page.setScaleX(scale);
page.setScaleY(scale);
//根据position设置界面上三张图片的偏移量,使左右两张图片也能在界面上显示
page.setTranslationX(-1100 * position);
}
}
PageTransformer
的使用:viewPager.setPageTransformer(true, new PageTransformer());
这里要特别说明,page.setTranslationX(-1100 * position)
、page.setScaleX(scale)
、page.setScaleY(scale)
、page.setRotationY(rorate)
,这四个方法的值要根据你项目的情况自己去调整大小
三、通过反射修改ViewPager
滑动速度
package com.hpplay.muiltythreaddemo.viewpagerdemo;
import android.content.Context;
import android.view.animation.Interpolator;
import android.widget.Scroller;
public class FixedSpeedScroller extends Scroller {
private int mDuration = 1500;
public FixedSpeedScroller(Context context) {
super(context);
}
public FixedSpeedScroller(Context context, Interpolator interpolator) {
super(context, interpolator);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
// Ignore received duration, use fixed one instead
super.startScroll(startX, startY, dx, dy, mDuration);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy) {
// Ignore received duration, use fixed one instead
super.startScroll(startX, startY, dx, dy, mDuration);
}
public void setmDuration(int time) {
mDuration = time;
}
public int getmDuration() {
return mDuration;
}
}
使用:
try {//调整ViewPager切换滑动速度
Field field = ViewPager.class.getDeclaredField("mScroller");
field.setAccessible(true);
FixedSpeedScroller scroller = new FixedSpeedScroller(viewPager.getContext(),
new AccelerateInterpolator());
field.set(viewPager, scroller);
scroller.setmDuration(400);
} catch (Exception e) {
}
四、控制ViewPager
对连续长按遥控器左右键的事件响应
如果不做处理,在用户按着遥控器左右键不松手的时候,ViewPager
会快速切换,使界面空白。这一点是在TV APP
开发中需要处理的,手机APP
开发中不用处理这一点
//控制ViewPager对连续长按遥控器左右键的事件响应
viewPager.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (System.currentTimeMillis() - lastKeyTime < 400) {
return true;
}
if(event.getAction() == KeyEvent.ACTION_UP){
lastKeyTime = -1l;
}else{
lastKeyTime = System.currentTimeMillis();
}
return false;
}
});
lastKeyTime
为全局变量,默认-1l
,private long lastKeyTime = -1l;
网友评论