欢迎访问 licqi IT技术
我们一直在努力

Android Studio – 第四十六期 不会ANR的轮播写法

最近在学习撸撸的代码,发现他的轮播写法很独特,但是有bug,就重新修改了一下,现在支持左右点击和圆点自定义。

BannerAdapter:(注意适配器自己看ImageView和onclick的自己项目的写法~)

package com.example.p029_banner_lunbo.adapter;

import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import com.example.p029_banner_lunbo.bannerutils.BannerView;
import com.example.p029_banner_lunbo.domain.Biaoge_listBean;

import java.util.List;


public class BannerAdapter extends BannerView.Adapter {

    private List mAdList;
    private Object mReceiver;

    public BannerAdapter(Object receiver, List items) {
        mReceiver = receiver;
        mAdList = items;
    }

    @Override
    public int getRealCount() {
        return mAdList.size();
    }

    @Override
    public Object instantiateItem(final ViewGroup container, int position) {
        int size = mAdList.size();
        if (size == 0) {
            return null;
        }

        final int pos = position % size;

        final Biaoge_listBean item = mAdList.get(pos);

        ViewGroup.LayoutParams p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        ImageView iv = new ImageView(container.getContext());
        iv.setScaleType(ImageView.ScaleType.FIT_XY);
        iv.setAdjustViewBounds(true);
        container.addView(iv, p);

        iv.setBackgroundResource(item.getImg_url());

//        GlideUtil.display(container.getContext(), iv, item.getPic_url(),
//                GlideOptionsFactory.get(GlideOptionsFactory.Type.RADIUS));

        iv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                MobEventHelper.onEvent(container.getContext(), "UI2_ec_index_banner");
//                    MobEventHelper.onEvent(container.getContext(), "UI2_ec_index_banner_" + String.valueOf(pos + 1));
                if (container.getContext() instanceof Activity) {
                    Activity act = (Activity) container.getContext();
                    //跳转bufen
//                    HiosHelper.resolveAd(act, mReceiver, item.getUrl());
                }
            }
        });

        return iv;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View) object);
    }
}

DotIndicatorView:(圆点的方法大部分都public了,大家可以DotIndicatorView.自定义~)

package com.example.p029_banner_lunbo.bannerutils;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;

/**
 * 圆点导航
 * @author geek
 *
 */
public class DotIndicatorView extends View {
   private Paint mPaint;

   private int mPadding;
   private int mCircleRadius;
   
   private int mCurrentColor;
   private int mNormalColor;
   
   private int mCount = 3;
   
   private int mCurrent;
   
   public DotIndicatorView(Context context) {
      super(context);
      initView();
   }
   
   public DotIndicatorView(Context context, AttributeSet attrs) {
      this(context, attrs, 0);
   }

   public DotIndicatorView(Context context, AttributeSet attrs, int defStyle) {
      super(context, attrs, defStyle);
      initView();
   }

   private void initView() {
      DisplayMetrics dm = getResources().getDisplayMetrics();
      mPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, dm);
      mCircleRadius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, dm);
      mCurrentColor = Color.WHITE;
      mNormalColor = Color.argb(88, 91, 91, 91);
      
      mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
   }
   
   @Override
   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      int width = mCircleRadius * 2 * mCount + mPadding * (mCount -1);
      int height = mCircleRadius * 2;
      
      setMeasuredDimension(width, height);
   }
   
   @Override
   protected void onDraw(Canvas canvas) {
      for (int i = 0; i < mCount; i++) {
         canvas.save();
         canvas.translate((mCircleRadius * 2 + mPadding) * i, 0);
         
         if(i == mCurrent) mPaint.setColor(mCurrentColor);
         else mPaint.setColor(mNormalColor);
         
         canvas.drawCircle(mCircleRadius , mCircleRadius, mCircleRadius, mPaint);
         canvas.restore();
      }
   }
   
   /**
    * 创建导航
    * @param count 个数
    */
   public void create(int count) {
      mCount = count;
      requestLayout();
      invalidate();
   }
   
   /** 
    * 选中当前
    * @param position 选中位置
    */
   public void current(int position) {
      mCurrent = position;
      invalidate();
   }
   
   /**
    * 获取当前选中的位置
    * @return
    */
   public int current() {
      return mCurrent;
   }
}

BannerView:(自定义的View~)

package com.example.p029_banner_lunbo.bannerutils;

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;

import com.example.p029_banner_lunbo.R;

import java.lang.ref.WeakReference;


public class BannerView extends FrameLayout {
    private static final int MSG_RUN = 1;

    private ViewPager mViewPager;
    /**
     * 导航的小点
     */
    private DotIndicatorView mIndicator;

    private Adapter mAdapter;

    /**
     * 是否处于滑动的状态
     */
    private boolean isScrolling;

    private int mIndicatorPosition; // center_hori  left
    /**
     * 是否显示indicator
     */
    private boolean isShowIndicator = true;

    private boolean isTouch;

    private Handler mHandler;

    private BannerViewHelper mHelper;

    private int mScrollTime;

    public BannerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BannerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.BannerView,
                defStyle, 0);
        mIndicatorPosition = ta.getInt(R.styleable.BannerView_indicator_position, 0);
        isShowIndicator = ta.getBoolean(R.styleable.BannerView_indicator_visible, true);
        mScrollTime = ta.getInteger(R.styleable.BannerView_scroll_time, 3000);
        isScrolling = ta.getBoolean(R.styleable.BannerView_auto_start, false);
        ta.recycle();
        initView(context);
    }

    private void initView(Context context) {
        mViewPager = new ViewPager(context);
        mViewPager.addOnPageChangeListener(mOnPageChangeListener);
        addView(mViewPager);//, viewPagerParams);

        mHandler = new H(mViewPager);
        mIndicator = new DotIndicatorView(context);
        LayoutParams indicatorParams =
                new LayoutParams(LayoutParams.WRAP_CONTENT,
                        LayoutParams.WRAP_CONTENT);
        if (mIndicatorPosition == 0) {
            indicatorParams.gravity = Gravity.BOTTOM | Gravity.LEFT;
        } else if (mIndicatorPosition == 1) {
            indicatorParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
        } else if (mIndicatorPosition == 2) {
            indicatorParams.gravity = Gravity.BOTTOM | Gravity.RIGHT;
        }
        indicatorParams.bottomMargin = 20;

        if (!isShowIndicator) {
            return;
        }
        addView(mIndicator, indicatorParams);

    }

    @Override
    protected void onAttachedToWindow() {
        if (isScrolling) {
            startScroll();
        }
        super.onAttachedToWindow();
        mHelper = new BannerViewHelper(this);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (mHelper != null) {
            mHelper.resolveTouchConflict(ev);
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.WRAP_CONTENT);
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new LayoutParams(getContext(), attrs);
    }

    @Override
    protected android.view.ViewGroup.LayoutParams generateLayoutParams(
            android.view.ViewGroup.LayoutParams p) {
        return new LayoutParams(p);
    }

    @Override
    protected boolean checkLayoutParams(android.view.ViewGroup.LayoutParams p) {
        return p instanceof LayoutParams;
    }

    private OnPageChangeListener mOnPageChangeListener = new OnPageChangeListener() {

        @Override
        public void onPageSelected(int position) {
            int relCount = mAdapter.getRealCount();
            if (relCount <= 1="" 0)="" {="" mindicator.current(0);="" }="" else="" mindicator.current(position="" %="" relcount);="" @override="" public="" void="" onpagescrolled(int="" arg0,="" float="" arg1,="" int="" arg2)="" onpagescrollstatechanged(int="" arg0)="" istouch="arg0" =="ViewPager.SCROLL_STATE_DRAGGING;" if="" (arg0="=" viewpager.scroll_state_idle="" &&="" isscrolling)="" mhandler.removemessages(msg_run);="" message="" msg="mHandler.obtainMessage(MSG_RUN," isscrolling="" ?="" :="" 0,="" 0);="" mhandler.sendmessagedelayed(msg,="" mscrolltime);="" };="" **="" *="" 开始自动滚动="" startscroll()="" 1,="" 停止自动滚动="" stopscroll()="" (mhandler="" !="null)" protected="" parcelable="" onsaveinstancestate()="" bundle="" bundle();="" bundle.putboolean("scroll",="" isscrolling);="" bundle.putparcelable("state",="" super.onsaveinstancestate());="" return="" bundle;="" onrestoreinstancestate(parcelable="" state)="" state;="" state="bundle.getParcelable("state");" (state="" super.onrestoreinstancestate(state);="" onattachedtowindow()="" super.onattachedtowindow();="" if(isscrolling)="" mhandler.sendemptymessage(msg_run);="" ondetachedfromwindow()="" super.ondetachedfromwindow();="" 设置banner的数据集合="" setadapter(adapter="" adapter)="" madapter="adapter;" mviewpager.setadapter(adapter);="" mindicator.create(adapter.getrealcount());="" 获取adapter="" adapter="" getadapter()="" madapter;="" getcurrent()="" mviewpager.getcurrentitem()="" +="" 1;="" setcurrent(int="" current)="" mviewpager.setcurrentitem(current);="" private="" static="" class="" h="" extends="" handler="" weakreference mViewPager;

        public H(ViewPager pager) {
            mViewPager = new WeakReference(pager);
        }

        public void handleMessage(Message msg) {
            if (mViewPager.get() == null) return;

            boolean isScrolling = msg.arg1 == 1;
            boolean isTouch = msg.arg2 == 1;

            if (msg.what == MSG_RUN && isScrolling) {
                if (!isTouch) {
                    int pos = mViewPager.get().getCurrentItem() + 1;
                    mViewPager.get().setCurrentItem(pos);
//             sendEmptyMessageDelayed(MSG_RUN, 3000);
                } else {
                    removeMessages(MSG_RUN);
                }
            }
        }
    }

    public static abstract class Adapter extends PagerAdapter {
        @Override
        public final int getCount() {
            return Integer.MAX_VALUE;
        }

        /**
         * 获取真实的数据统计
         *
         * @return
         */
        public abstract int getRealCount();

        @Override
        public final boolean isViewFromObject(View arg0, Object arg1) {
            return arg0 == arg1;
        }

        public Object getItem(int position) {
            return position;
        }
    }
}

BannerViewHelper:(用于解决BannerView和SwipeRefreshLayout的冲突)

package com.example.p029_banner_lunbo.bannerutils;

import android.support.v4.widget.SwipeRefreshLayout;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewGroup;


/**
 * 用于解决BannerView和SwipeRefreshLayout的冲突
 * @author geek
 *
 */
public class BannerViewHelper {
   private BannerView mBannerView;
   private SwipeRefreshLayout mSwipeRefreshLayout;
   
   private VelocityTracker mVelocityTracker;
   
   private float mAccuracy = 1.f;
   
   public BannerViewHelper(BannerView bannerView) {
      mBannerView = bannerView;
      mSwipeRefreshLayout = findSwipeRefreshLayout();
   }
   
   public BannerViewHelper(BannerView bannerView, float accuracy) {
      this(bannerView);
      mAccuracy = accuracy;
   }
   
   public void resolveTouchConflict(MotionEvent event) {
      if(mSwipeRefreshLayout == null) return;
      
      setupVelocityTracker(event);
      switch (event.getAction()) {
      case MotionEvent.ACTION_MOVE:
         if(!mSwipeRefreshLayout.isEnabled()) return;
         mVelocityTracker.computeCurrentVelocity(1000);
         if(Math.abs(mVelocityTracker.getXVelocity()) > 
            Math.abs(mVelocityTracker.getYVelocity()) * mAccuracy) {
            mSwipeRefreshLayout.setEnabled(false);
         }
         break;
      case MotionEvent.ACTION_UP:
      case MotionEvent.ACTION_CANCEL:
         mSwipeRefreshLayout.setEnabled(true);
         recycleVelocityTracker();
      default:
         break;
      }
   }
   
   private void setupVelocityTracker(MotionEvent event) {
      if(mVelocityTracker == null) mVelocityTracker = VelocityTracker.obtain();
      mVelocityTracker.addMovement(event);
   }
   
   private void recycleVelocityTracker() {
      if(mVelocityTracker != null) {
         mVelocityTracker.clear();
         mVelocityTracker.recycle();
         mVelocityTracker = null;
      }
   }
   
   private SwipeRefreshLayout findSwipeRefreshLayout() {
      ViewGroup parent = (ViewGroup) mBannerView.getParent();
      while(parent != null && parent.getId() != android.R.id.content) {
         if(parent instanceof SwipeRefreshLayout) return (SwipeRefreshLayout) parent;
         parent = (ViewGroup) parent.getParent();
      }
      return null;
   }
}

xml布局:



    

        

    

    

    

调用方法:

tv_left = (TextView) findViewById(R.id.tv_left);
tv_left.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        //左←
        ToastUtil.showToastShort(MainActivity.this, "左");

        mBannerView.setCurrent(mBannerView.getCurrent() - 2);
    }
});
tv_right = (TextView) findViewById(R.id.tv_right);
tv_right.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        //右→
        ToastUtil.showToastShort(MainActivity.this, "右");

        mBannerView.setCurrent(mBannerView.getCurrent());
    }
});
mBannerView = (BannerView) findViewById(R.id.banner);

Data1();
mBannerView.setAdapter(new BannerAdapter(this, mList1));

mBannerView.stopScroll();
mBannerView.startScroll();

代码已经整理好,效果如下图:

图1:

图2:

图2:

地址:https://github.com/geeklx/MyApplication/tree/master/p029_banner_lunbo

附:

赞(0) 打赏
未经允许不得转载:licqi IT技术 » Android Studio – 第四十六期 不会ANR的轮播写法
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏