Android Studio - 第四十六期 不会AAR的轮播写法

最近在学习撸撸的代码,发现他的轮播写法很独特,但是有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

附:

时间: 2024-12-19 05:30:58

Android Studio - 第四十六期 不会AAR的轮播写法的相关文章

Android Studio - 第四十八期 模块ViewPager+Fragment

最近一直在review撸撸的代码,发现了一种模块的写法,非常不错,独立出来,希望能帮到你~ 如果你遇到这样的页面,怎么办,不会把所有代码都写到一个页面中吧~,这样看你代码的人会骂死你的吧~我想~而且如果不同的版本要用不同的位置,大小也不一样,难道你要重新布局嘛~这都是开发中需要纠结的,下面就开始正题了,这是利用了以前讲过的多版本打版以及配置多Fragment加载巧妙的解决了复杂的页面逻辑,我数了数,首页代码不到一百行,厉害吧~哈哈哈哈~ 在写这样的页面之前给大家介绍一下怎么写一个页面模块代码.

Android Studio - 第四十五期 Gradle manifestPlaceholders

最近在学习撸撸的代码规范和写法,有些心得,准备好好写一写~包括了多渠道打版(以前有写过方法),工厂模式,mvp,以及最近刚封装出来的多渠道多版本展示不同页面的manifestPlaceholders的配置方法,大家应该也碰到过线上和线下环境的切换换地址,换私钥的头大问题,本篇就来解决这些问题. 先在androidmanifest文件配置一个节点,这里以极光为例: <meta-data             android:name="JPUSH_APPKEY"         

Android Studio 第五十六期 - Android之系统设置选项的包名

以com.android.settings开头的形式: com.android.settings.Settings 手机系统设置 com.android.settings.WirelessSettings 无线和网络设置 com.android.settings.AccessibilitySettings 辅助功能设置 com.android.settings.ActivityPicker 选择活动 com.android.settings.ApnSettings APN设置 com.andro

Android Studio第三十六期 - 模块化Activity管理Fragment

代码已经整理好.效果如下图: 图1: 图2: 地址:https://github.com/geeklx/MyApplication/tree/master/p010_recycleviewall/src/main/java/com/example/p010_recycleviewall/shoucang

Android Studio 第七十六期 - Android webview长按识别二维码

代码已经整理好,效果如下图: 地址:https://github.com/geeklx/myapplication2018/tree/master/p019_shibie_qrcode 原文地址:http://blog.51cto.com/liangxiao/2150604

Android Studio第四十期 - 上传头像功能支持权限管理

代码已经整理好,加了权限管理和SP保存上传服务器的方法,希望能够帮到大家~效果如下图: 地址:https://github.com/geeklx/MyApplication/tree/master/p025_upload_img 附:这里借鉴了翔神(http://blog.csdn.net/lmj623565791/article/details/72859156)的写法,大家可以好好学习一下~哈哈~

Android第四十六期 - 微信关闭Activity效果SwipeBack

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

从零开始学android&lt;android基本绘图.四十六.&gt;

在一般的图形绘制中用户往往只需要覆写onDraw()方法即可,可是如果要想真正的完成绘图的操作,还需要掌握四个核心的操作类: android.graphics.Bitmap:主要表示的是一个图片的存储空间,所包含的图片可以来自于文件或由程序创建: android.graphics.Paint:主要的绘图工具类,可以指定绘图的样式: android.graphics.Canvas:是一个操作绘图以及Bitmap的平台,相当于提供了一个画板的功能,在onDraw()方法的参数中也定义了此类型的参数,

Android Studio - 第四十三期 RecyclerView存在大量Item时,当滚到底部时快速滑到顶部

在使用RecyclerView展示图片或者其他信息时,往往需要展示很多的Item,当滚到底部时又想回到顶部,如果一点一点的向上划去比较麻烦,而且用户体验不好.因此添加一个快速回到顶部的按钮是很有必要的,并且刚开始的时候这个按钮是隐藏的,当滑动超过超过一屏的时候才会出现,在滑动的过程中也是不会出现的.很多类似的项目都会使用到,但是如何在快速回到顶部的过程中不出现卡顿,体现的很是流畅,这点很重要.下面是我根据网上的方法自己修改的一个可以快速回到顶部的类,在此做一下备注,以便日后查看: 1.FastS