1. 程式人生 > >Android Studio - 第四十六期 不會AAR的輪播寫法

Android Studio - 第四十六期 不會AAR的輪播寫法

android banner

最近在學習擼擼的代碼,發現他的輪播寫法很獨特,但是有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<Biaoge_listBean> mAdList;
    private Object mReceiver;

    public BannerAdapter(Object receiver, List<Biaoge_listBean> 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 <= 0) {
                mIndicator.current(0);
            } else {
                mIndicator.current(position % relCount);
            }
        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {

        }

        @Override
        public void 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 ? 1 : 0, isTouch ? 1 : 0);
                mHandler.sendMessageDelayed(msg, mScrollTime);
            }
        }
    };

    /**
     * 開始自動滾動
     */
    public void startScroll() {
        mHandler.removeMessages(MSG_RUN);
        isScrolling = true;
        Message msg = mHandler.obtainMessage(MSG_RUN, 1, isTouch ? 1 : 0);
        mHandler.sendMessageDelayed(msg, mScrollTime);
    }

    /**
     * 停止自動滾動
     */
    public void stopScroll() {
        isScrolling = false;
        if (mHandler != null) {
            mHandler.removeMessages(MSG_RUN);
        }
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        Bundle bundle = new Bundle();
        bundle.putBoolean("scroll", isScrolling);
        bundle.putParcelable("state", super.onSaveInstanceState());
        return bundle;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        Bundle bundle = (Bundle) state;
        isScrolling = bundle.getBoolean("scroll");
        state = bundle.getParcelable("state");
        if (state != null) {
            super.onRestoreInstanceState(state);
        }
    }

// @Override
// protected void onAttachedToWindow() {
//    super.onAttachedToWindow();
//    if(isScrolling) mHandler.sendEmptyMessage(MSG_RUN);
// }

    @Override
    protected void onDetachedFromWindow() {
        mHandler.removeMessages(MSG_RUN);
        super.onDetachedFromWindow();
    }

    /**
     * 設置banner的數據集合
     */
    public void setAdapter(Adapter adapter) {
        mAdapter = adapter;
        mViewPager.setAdapter(adapter);
        mIndicator.create(adapter.getRealCount());
    }

    /**
     * 獲取adapter
     */
    public Adapter getAdapter() {
        return mAdapter;
    }

    public int getCurrent() {
        return mViewPager.getCurrentItem() + 1;
    }

    public void setCurrent(int current) {
        mViewPager.setCurrentItem(current);
    }

    private static class H extends Handler {
        private WeakReference<ViewPager> 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布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ccc"
        android:orientation="vertical">

        <com.example.p029_banner_lunbo.bannerutils.BannerView
            android:id="@+id/banner"
            android:layout_width="match_parent"
            android:layout_height="400dp"
            app:indicator_position="center"
            app:indicator_visible="false"
            app:scroll_time="8000" />

    </LinearLayout>

    <TextView
        android:id="@+id/tv_left"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/icon_left" />

    <TextView
        android:id="@+id/tv_right"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:background="@drawable/icon_right" />
</RelativeLayout>

調用方法:

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:

技術分享

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

附:

技術分享


本文出自 “梁肖技術中心” 博客,請務必保留此出處http://liangxiao.blog.51cto.com/3626612/1953066

Android Studio - 第四十六期 不會AAR的輪播寫法