草庐IT

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

吴雨声 2023-03-28 原文
    最近在学习撸撸的代码,发现他的轮播写法很独特,但是有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

    附:

    



有关Android Studio - 第四十六期 不会ANR的轮播写法的更多相关文章

  1. ruby - Highline 询问方法不会使用同一行 - 2

    设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案

  2. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  3. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  4. ruby-on-rails - prawnto 显示新页面时不会中断的表格 - 2

    我有可变数量的表格和可变数量的行,我想让它们一个接一个地显示,但如果表格不适合当前页面,请将其放在下一页,然后继续。我已将表格放入事务中,以便我可以回滚然后打印它(如果高度适合当前页面),但我如何获得表格高度?我现在有这段代码pdf.transactiondopdf.table@data,:font_size=>12,:border_style=>:grid,:horizontal_padding=>10,:vertical_padding=>3,:border_width=>2,:position=>:left,:row_colors=>["FFFFFF","DDDDDD"]pdf.

  5. ruby - 在 Ruby 中将字符串转换为十六进制 - 2

    我正在尝试使用Ruby将二进制文件转换为十六进制。目前我有以下内容:File.open(out_name,'w')do|f|f.puts"constunsignedintmodFileSize=#{data.length};"f.puts"constcharmodFile[]={"first_line=truedata.bytes.each_slice(15)do|a|line=a.map{|b|",#{b}"}.joiniffirst_linef.putsline[1..-1]elsef.putslineendfirst_line=falseendf.puts"};"end这是以下代

  6. ruby-on-rails - 使用 ApplicationController.renderer.render 从 Controller 外部渲染的 Rails 5 不会在自身上设置变量 - 2

    我正在使用Rails5ApplicationController.renderer.render方法从模型中进行渲染。我需要将一些变量传递给我的布局,这是我使用locals选项完成的;如果直接访问此变量,则该变量在布局中可用,但不能通过self访问。这是我设置渲染的方式html_string=ApplicationController.renderer.render(file:"/#{template_path}/base/show",:formats=>[:pdf,:html],locals:{:@routing_form=>self,:controller_name=>contro

  7. ruby - 十六进制字符串到 Ruby 中的 signed int 转换 - 2

    如何在ruby​​中将十六进制字符串转换为32位有符号整数?例如a="fb6d8cf1"#hexstring[a].pack('H*').unpack('l')#fromthedocumentationitunpackstoits32bitsignedint它转换为-242455045但实际答案是-76706575你能指出我做错了什么吗? 最佳答案 您似乎遇到了字节序问题。这给出了期望的结果:[a].pack("H*").unpack("l>")#=>[-76706575]["038a67f90"].pack("H*").unpac

  8. ruby-on-rails - Ruby:给定日期找到下一个第二或第四个星期二 - 2

    我似乎找不到一种优雅的方式来做到这一点......给定一个日期,我如何找到下一个星期二,即日历月的第2个或第4个星期二?例如:给定2012-10-19然后返回2012-10-23或给定2012-10-31然后返回2012-11-13OctoberNovemberSuMoTuWeThFrSaSuMoTuWeThFrSa12345612378910111213456789101415161718192011121314151617212223242526271819202122232428293031252627282930 最佳答案

  9. ruby - 如何验证字符串是 Ruby 中的正确十六进制值? - 2

    我正在用Ruby编写一个6502汇编器。我正在寻找一种方法来验证字符串形式的十六进制操作数。我知道String对象提供了一个“十六进制”方法来返回一个数字,但是我遇到了一个问题:"0A".hex#=>10-avalidhexadecimalvalue"0Z".hex#=>0-invalid,producesazero"asfd".hex#=>10-Why10?Iguessitreads'a'firstandstopsat's'?输入一堆乱码会得到一些奇怪的结果。我需要的是一种方法来首先验证该值是合法的十六进制字符串。我在玩正则表达式,并意识到我可以做到这一点:trueif"0A"=~/

  10. ruby - apt Recipe 不会安装在我的 Recipe 中 - 2

    我正在尝试使用Vagrant创建我的第一个ChefRecipe,但在第一步就遇到了问题。我的Recipe的第一行是:include_recipe"apt"但是当我尝试vagrantprovision时,出现以下错误:==>default:[2014-09-21T07:15:42+00:00]WARN:MissingCookbookDependency:==>default:Recipe`apt`isnotintherun_list,andcookbook'apt'==>default:isnotadependencyofanycookbookintherun_list.Toloadth

随机推荐