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<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:
图2:
地址:https://github.com/geeklx/MyApplication/tree/master/p029_banner_lunbo
附:

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
利用Swarmkit构建Windows/Linux混合Docker集群
在很多公司都同时存在Windows+Linux两种操作系统,在Linux上跑Docker很方便各种资料文档齐全,但是在Windows上跑Docker相对比较少,同时也受到一些限制,如Windows上docker网络问题。下面就介绍下利用Windows IIS跑Web应用,同时使用Haproxy作为负载均衡器。 方案采用Windows原生container、docker swarmkit、负载均衡器采用Haproxy+Etcd+Confd 流程说明: 开发及运维修改dockerfile及代码提交至SVN服务器,同时触发SVN钩子进行镜像构建(Windows项目在Windows构建、Linux项目在Linux构建),并push至我们的Docker私有仓库 推送镜像之后,钩子同时触发Docker Swarmkit集群的leader服务器进行服务创建或者更新 启动IIS容器,需要提前启动haproxy+etcd+confd容器,以便服务注册 Windows Docker Swarm初始化集群集群,不可以只使用docker swarm init,而不指定IP及端口,否则就会一直卡在初始化的进程下...
- 下一篇
企业中MySQL高可用集群架构三部曲之MM+keepalived
各位老铁们,老张与大家又见面了。看到各位在博客里面给我的留言和访问量的情况,我很是欣慰,也谢谢大家对我的认可。我写这些博客,就是想把自己对于MySQL数据库的一些看法和自己平时的实战经验分享出来,我们可以一起探讨,共同进步。也保证今后只要一有空就更新博文,推出更多的干货。 我的学生经常对我说:“张老师,每次我遇到报错,有时还是会百度,但是最烦的是不知道百度哪篇帖子说的是正确的".其实这些呢,都是因为自己还没有对MySQL数据库核心知识的不熟悉,和对技术掌握的不牢固。平时下得功夫还是不到位。我们做技术这个行业,还是需要自己给自己加发条,促使自己每天都要学习一些新的知识。理论配合实验一起,先要学会多问自己几个问题,一个实验多做几遍,可能会得到不同的实验效果。学习知识要踏实下来,学会多做实验总结。我想今后再遇到报错,可能自己就会有一个清晰的解题思路,这个需要一定时间的磨练。 也有人经常问Oracle和MySQL到底有啥区别,其实MySQL数据库上手很简单,难的是后期架构的设计与维护。老张三部曲中第一部曲MHA希望对大家在线上部署方面有帮助。 今儿给大家介绍第二部曲,MM+keepalived...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS关闭SELinux安全模块
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS8安装Docker,最新的服务器搭配容器使用
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Windows10,CentOS7,CentOS8安装Nodejs环境
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2整合Redis,开启缓存,提高访问速度