目标
实现图片自动轮播,允许用户自主滑动,响应单击事件
参考
http://www.imooc.com/learn/793
文档列表
- MainActivity 活动页
- MyFrameLayout 自定义FrameLayout类
- MyViewPager 自定义ViewPager类
- MyPagerTransfomer 自定义ViewPager切换动画
- layout目录下activity_main 活动页布局
- drawable目录下dot_normal.xml与dot_selected.xml 小圆点绘制
activity_main布局
仅包含一个自定义MyFrameLayout
<com.cetc.demo.MyFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/myFramelayout">
</com.cetc.demo.MyFrameLayout>
MainActivity
- 实例化一个MyFrameLayout对象,
- 将准备在界面轮播图片的资源ID定义为一个数组
- 调用MyFrameLayout的初始化方法,将数组传入
- 如需监听单击事件,需要implements对应的监听接口,书写监听逻辑。
public class MainActivity extends AppCompatActivity implements MyFrameLayout.UserClickedListener {
//把准备轮播的图片资源ID组成一个数组
private int[] imagesIDs = new int[]{
R.drawable.a,
R.drawable.b,
R.drawable.c,
};
MyFrameLayout myFrameLayout;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_framelayout);
myFrameLayout = (MyFrameLayout)findViewById(R.id.myFramelayout);
//调用初始化方法,需要传入资源ID数组
myFrameLayout.intiFrameLayout(imagesIDs);
//添加监听
myFrameLayout.setUserClickedListener(this);
}
//自己实现单击逻辑
@Override
public void userClicked(int position) {
Toast.makeText(this, " "+position, Toast.LENGTH_SHORT).show();
}
}
至此前台使用已经说明完毕,在任何工程中使用只需复制以下五个文档到工程中,参照上面的代码书写即可实现目标。
自定义切换动画
代码为Google官方示例代码,效果为缩放缓出缓进。在MyViewPager的构造方法中调用。想换成其他动画效果,改写transformPage()方法即可。
public class CustomPageTransformer implements ViewPager.PageTransformer {
private static final float MIN_SCALE = 0.75f;
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 0) { // [-1,0]
// Use the default slide transition when moving to the left page
view.setAlpha(1);
view.setTranslationX(0);
view.setScaleX(1);
view.setScaleY(1);
} else if (position <= 1) { // (0,1]
// Fade the page out.
view.setAlpha(1 - position);
// Counteract the default slide transition
view.setTranslationX(pageWidth * -position);
// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE
+ (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}
自定义MyViewPager
public class MyViewPager extends ViewPager {
private int index = 0;// 当前页码编号
private boolean isClick;//是否是点击事件,true代表点击事件
private boolean isAuto;//是否开启轮播,ture代表开启
private ClickEventListener clickEventListener;
public ClickEventListener getClickEventListener() {
return clickEventListener;
}
public void setClickEventListener(ClickEventListener clickEventListener) {
this.clickEventListener = clickEventListener;
}
//使用Timer/TimerTask/Handler完成定时播放任务
private Timer timer = new Timer();
private Handler autoHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
//传入1时代表开启轮播
case 1:
//改变viewpager当前显示
if (++index>getChildCount()){
index = 0;
}
setCurrentItem(index);//设置viewpager当前Item值,从而改变图片
break;
}
}
};
//两个构造函数,需要在构造函数中配置自定义ViewPager
public MyViewPager(Context context) {
super(context);
initViewpager();
}
public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
initViewpager();
}
//配置自定义ViewPager
private void initViewpager() {
setPageTransformer(true, new CustomPageTransformer());//设置页面转换时动画效果
setAuto(true);//默认开启轮播
startScroll();//开启定时任务
}
/**
* 用户点击事件处理
*
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN://按下时
setAuto(false);
isClick = true;
break;
case MotionEvent.ACTION_MOVE://滑动时
isClick = false;//有滑动则不会是单击事件
case MotionEvent.ACTION_UP//抬起时
setAuto(true);
if (isClick){
//如果是单击事件则执行
clickEventListener.clickImageIndex(getCurrentItem());
}
break;
}
return super.onTouchEvent(event);
}
//轮播设置
public void setAuto(boolean b){
isAuto = b;
}
private void startScroll(){
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
if (isAuto) {
autoHandler.sendEmptyMessage(1);
}
}
};
timer.schedule(timerTask,3000,10000);
}
//定义单击事件的接口,具体逻辑交给调用方事件。这里交给了MyFrameLayout类
public interface ClickEventListener{
void clickImageIndex(int position);//当前图片的位置
}
}
自定义MyFrameLayout
public class MyFrameLayout extends FrameLayout implements
MyViewPager.OnPageChangeListener,MyViewPager.ClickEventListener {
private int[] imagesIDs;
MyViewPager myViewPager;
LinearLayout linearLayout;
private UserClickedListener userClickedListener;
public UserClickedListener getUserClickedListener() {
return userClickedListener;
}
public void setUserClickedListener(UserClickedListener userClickedListener) {
this.userClickedListener = userClickedListener;
}
//三个构造函数,有log可以查看调用的是哪一个。
//在构造函数中给FrameLayout添加具体布局
//initViewPager()添加展示滚动图片所在的viewpager
// initDotLinearLayout()添加底部小圆点所在的LinearLayout
//注意:FrameLayout中后添加的View在顶层
public MyFrameLayout(@NonNull Context context) {
super(context);
Log.d(TAG, "MyFrameLayout: "+1);
initViewPager();
initDotLinearLayout();
}
public MyFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
Log.d(TAG, "MyFrameLayout: "+2);
initViewPager();
initDotLinearLayout();
}
public MyFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
super(context, attrs, defStyleAttr);
Log.d(TAG, "MyFrameLayout: "+3);
initViewPager();
initDotLinearLayout();//FrameLayout中后添加的View在顶层
}
private void initDotLinearLayout(){
linearLayout = new LinearLayout(getContext());
FrameLayout.LayoutParams lp1 = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,80);
linearLayout.setLayoutParams(lp1);
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
linearLayout.setAlpha(0.5f);
linearLayout.setGravity(Gravity.CENTER);
linearLayout.setBackgroundColor(0xF5F5F5);
FrameLayout.LayoutParams lp2 = (LayoutParams)linearLayout.getLayoutParams();
lp2.gravity = Gravity.BOTTOM;
linearLayout.setLayoutParams(lp2);
addView(linearLayout);
}
private void initViewPager(){
myViewPager = new MyViewPager(getContext());
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout..LayoutParams.MATCH_PARENT);
myViewPager.setLayoutParams(lp);
myViewPager.addOnPageChangeListener(this);
myViewPager.setClickEventListener(this);
addView(myViewPager);
}
//获取到资源ID,将对应的图片加入到myViewPager中
//在底部LinerLayout中添加imagesID.length个圆点
public void intiFrameLayout(int[] imagesIDs){
this.imagesIDs= imagesIDs;
addImagesToViewPager();
for (int ignored : imagesIDs) {
addDotToLinearLayout();
}
}
private void addImagesToViewPager() {
//添加对应位置的图片到viewpager中
myViewPager.setAdapter(new MyViewPagerAdapter());
}
private void addDotToLinearLayout(){
//添加imagesID.length个圆点
ImageView img = new ImageView(getContext());
LinearLayout.LayoutParams lp =
new LinearLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT);
img.setLayoutParams(lp);
img.setPadding(8,10,8,10);
if(linearLayout.getChildCount()==0){
img.setImageResource(R.drawable.dot_selected);//默认第一个原点为选中状态
}else {
img.setImageResource(R.drawable.dot_normal);
}
linearLayout.addView(img);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
int count = linearLayout.getChildCount();
for (int i = 0; i <count ; i++) {
ImageView img = (ImageView)linearLayout.getChildAt(i);
if (i==position){
img.setImageResource(R.drawable.dot_selected);
}else {
img.setImageResource(R.drawable.dot_normal);
}
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
//实现MyViewPager中的单击事件响应接口
@Override
public void clickImageIndex(int position) {
userClickedListener.userClicked(position);//使用接口向上传递点击事件
}
//单击事件响应逻辑接口,具体逻辑由调用方实现。这里是由MainActivity实现
public interface UserClickedListener{
void userClicked(int position);
}
//myViewPager的Adapter
private class MyViewPagerAdapter extends PagerAdapter {
@Override
public int getCount() {
return imagesIDs.length;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public void destroyItem(ViewGroup container, int position,
Object object)
{
container.removeView((View) object);
}
@Override
public Object instantiateItem(ViewGroup container, int position)
{
ImageView imageView = new ImageView(getContext());
imageView.setImageResource(imagesIDs[position]);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
container.addView(imageView);
return imageView;
}
}
}
小圆点绘制
dot_normal.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@android:color/darker_gray"/>
<size android:height="8dp" android:width="8dp"/>
</shape>
dot_selected.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@android:color/holo_red_dark"/>
<size android:height="8dp" android:width="8dp"/>
</shape>