Androidは、糸の滑りを実現する自動ルーニーコントロールの実例コードです。


前言
現在多くのアプリには自動的に巡回放送されているbannerインターフェイスがあり、広告写真を展示したり、現在の人気のある活動を表示するために使用されています。よりクールな効果を備えているほか、インターフェースの占有率を減らすために、インターフェースの占用も素晴らしい設計点です。本論文は主に自動ルーニーコントロールの実現過程を総括し、これらのコントロールに対して最適化する技術である。
どのように実現しますか
私たちのコードのプログラミングを開始する前に、まず考えてみます。Googleが提供する公式アプリの中には、似たようなコントロールが実現されていますか?コントロールの安定性も相対的に保障されます。
よくある主流のコントロールの中で、実はViePagerとRecyclerViewはすでに類似の機能を実現しました。特にView Pagerはすでに私達のコントロールの大部分の機能を実現したと言ってもいいです。だから、ViewPagerに基づいて改造すれば、私達の巡回コントロールをより安定させることができます。
View Pagerと私たちが必要とする自動中継コントロールの差はどれぐらいですか?主に二つがあります。
  • は自動再生に対応していません。
  • 最後の枚から第一枚の
  • までスライドできません。
    したがって、私たちは主にこの二つの部分に対して対応する改造を行い、それによって自分たちの自動ロードショーコントロールを実現します。
    1.1自動ルーニー機能の実現
    自動ルーニー機能を実現するには、TimerやSchduledExectorServiceを通じてタイマーの機能を実現し、ViePagerをserCurentItem法により、現在のItemを次のpositionのデータに設定することを最初に考えましたが、タイマーで実現すると、問題があります。それは、私たちがbannerに放送を停止させたい時は面倒なので、Handlerを通じてsendMessageという形でイベントの送信を行い、Viewer Pagerの自動ロードショーを実現したり、シーンによっては停止するのが合理的です。
    コードを見に来ました。
    
     private static class AutoScrollHandler extends Handler {
    
     private WeakReference<AutoScrollViewPager> mBannerRef;
    
     private static final int MSG_CHANGE_SELECTION = 1;
    
     AutoScrollHandler(AutoScrollViewPager autoScrollViewPager) {
      mBannerRef = new WeakReference<>(autoScrollViewPager);
     }
    
     private void start() {
      removeMessages(MSG_CHANGE_SELECTION);
      sendEmptyMessageDelayed(MSG_CHANGE_SELECTION, AUTO_SCROLL_TIME);
     }
    
     private void stop() {
      removeMessages(MSG_CHANGE_SELECTION);
     }
    
     @Override
     public void handleMessage(Message msg) {
      if (msg.what == MSG_CHANGE_SELECTION) {
      if (mBannerRef == null || mBannerRef.get() == null) {
       return;
      }
      AutoScrollViewPager banner = mBannerRef.get();
    
      if (banner.mSelectedIndex == Integer.MAX_VALUE) {
       int rightPos = banner.mSelectedIndex % banner.mBannerList.size();
       banner.setCurrentItem(banner.getInitPosition() + rightPos + 1, true);
      } else {
       if (!hasMessages(MSG_CHANGE_SELECTION)) {
       banner.setCurrentItem(banner.mSelectedIndex + 1, true);
       sendEmptyMessageDelayed(MSG_CHANGE_SELECTION, AUTO_SCROLL_TIME);
       }
      }
    
      }
     }
     }
    外部のViewer Pagerに先に入って、弱い引用でメモリの流出を防止します。handle Message()メソッドでset CurrenntItem()メソッドを呼び出して、現在のViewer PagerのItemを対応するposition+1のデータに設定しますので、外部でHandlerのsendMessage()メソッドを呼び出します。ViewPagerは自動的に無限のルーレットを行うことができます。
    1.2 ViewPagerを最後の枚から最初の枚にスライドさせます。
    ビューPagerは最後のページから最初のページにスライドできないということは知っていますが、ビューPagerのAdapterの中にいれば、get Count()の方法でView Pagerのサイズを無限大に設定して、スライドのページがデータソースに対応しているデータを残りの方法で保証します。これにより、最後の1枚から1枚目までスライドさせる効果が得られます。
    
     public int getCount() {
      if (mBannerList == null) {
       return 0;
      }
      if (mBannerList.size() == 1) {
       return 1;
      } else {
       return Integer.MAX_VALUE;
      }
     }
    
     public Object instantiateItem(ViewGroup container, final int position) {
      if (mBannerList != null && mBannerList.size() > 0) {
       View imageView = null;
       Uri uri = Uri.parse(mBannerList.get(position % mBannerList.size()).cover_url); //        
       imageView = new SimpleDraweeView(mContext);
       ((SimpleDraweeView) imageView).setImageURI(uri);
       container.addView(imageView);
       return imageView;
      }
      return null;
     }
    二、どうやって最適化するか
    上記では簡単にViewer Pagerの自動ルーニー機能を実現しただけですが、実際にはまだ多くの詳細があります。例えば、Viewer Pagerのサイズを無限大に設定することによって、最後の1枚から1枚目までスライドできるようになります。私たちはAdapterのinstantiateItem(View Group container、final int position)の方法の中で、たくさんの新しいnewの出てくるViewを返す必要があります。このように不必要なメモリの浪費をもたらします。これらの細部を最適化してこそ、コントロールがより使いやすく、安定性と性能も優れています。
    2.1キャッシュによるメモリロスの低減
    View Pagerが無線中継の機能を実現するために、get Count()の大きさを無限大に設定して実現しましたが、これは問題が発生します。これはAdapterのinstantiateItem()方法の中で多くの新しいnewからのViewを返して、不要なメモリの浪費をもたらします。
    ですから、私たちはListをキャッシュ・プールとして利用できます。AdapterのdestroyItem()方法で廃棄されたObjectをキャッシュ・プールに預けて、繰り返し利用することで、メモリの無駄を避けることができます。
    
     private final ArrayList<View> mViewCaches = new ArrayList<>();
    
     @Override
     public void destroyItem(ViewGroup container, int position, Object object) {
      ImageView imageView = (ImageView) object;
      container.removeView(imageView);
      mViewCaches.add(imageView);
     }
    そして、AdapterのinstantiateItem()方法では、キャッシュされたViewをListから取り出し、繰り返し利用する。
    
     public Object instantiateItem(ViewGroup container, final int position) {
      if (mBannerList != null && mBannerList.size() > 0) {
       View imageView = null;
       Uri uri = Uri.parse(mBannerList.get(position % mBannerList.size()).cover_url);
       if (mViewCaches.isEmpty()) {
        imageView = new SimpleDraweeView(GlobalContext.getContext());
       } else {
        //          ,    
        imageView = (ImageView) mViewCaches.remove(0);
       }
     }
    2.2適切な自動ルーニーの停止
    Bannerに触ったり、現在展示されているBannerのページを離れたりすると、Bannerが無線でローテーションを続けていると、不要な性能が失われますので、Bannerと現在のActivityが見えない状態に触れている間はBannerのローテーションを停止し、性能を向上させます。
    
     public boolean dispatchTouchEvent(MotionEvent ev) {
      int action = ev.getAction();
      if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL
        || action == MotionEvent.ACTION_OUTSIDE) {
       startAutoPlay();
      } else if (action == MotionEvent.ACTION_DOWN) {
       stopAutoPlay();
      }
      return super.dispatchTouchEvent(ev);
     }
    2.3 View Pager切替速度を変更する
    生のViewer Pagerは自動ルーニーを行う時、切り替え速度がとても速くて、唐突な感じがします。また、Viewer Pagerもインターフェースを提供してくれません。Viewer Pagerに切り替え速度の設定をします。だから、反射方式でSrollerを使って速度の設定を切り替える必要があります。
    
     public AutoScrollViewPager(Context context) {
      this(context, null);
      initViewPagerScroll();
     }
    
     private void initViewPagerScroll() {
      try {
       Field mField = ViewPager.class.getDeclaredField("mScroller");
       mField.setAccessible(true);
       BannerScroller scroller = new BannerScroller(getContext());
       mField.set(this, scroller);
      } catch (Exception e) {
       Log.d(TAG, e.getMessage());
      }
     }
    
    public class BannerScroller extends Scroller {
    
     private static final int BANNER_DURATION = 1000;
     private int mDuration = BANNER_DURATION;
    
     public BannerScroller(Context context) {
      super(context);
     }
    
     @Override
     public void startScroll(int startX, int startY, int dx, int dy, int duration) {
      super.startScroll(startX, startY, dx, dy, mDuration);
     }
    }
    ここまで、私たちの自動ロードショーコントロールは、性能的にも安定的にも非常に優れています。
    締め括りをつける
    以上はこの文章の全部の内容です。本文の内容は皆さんの学習や仕事に対して一定の参考となる学習価値を持っています。質問があれば、メッセージを書いて交流してください。ありがとうございます。