Question

I want to implement a rotating banner. What control is best suitable for such UI?

here is what it needs to do:

  1. rotate 1 image per view
  2. rotate them only on swipe (or what's called onFling())
  3. remember the index of the current banner and show next banner when user is redirected onto another activity
  4. rotation is infinite in both directions

So essentially when you land on first activity the first index is shown. When you do swipe it should show next or previous image depending if the swipe is to the left or to the right. This should iterate in the infinite loop.

Thank you in advance

Was it helpful?

Solution

In case anybody wanted the solution, here is the code:

public class CustomBanner extends RelativeLayout {
        //================================================================================
        //==== declaration.
        protected List<Banner> _items = new ArrayList<Banner>();
        protected GestureDetector gestureDetector;
            protected View.OnTouchListener gestureListener;
            protected ImageView _banner = null;
        protected String TAG = "CustomBanner";
        //================================================================================

        //================================================================================
        //==== properties
        /**
         * This property pulls the banners from the state manager. If the banners are not there they will be pulled from the database.
         * */
        protected List<Banner> getBanners()
        {
            // get your banners however way you get them
            return this._items;
        }
        //================================================================================

        //================================================================================
        //==== constructors
        public CustomBanner(Context context, AttributeSet attributes)
        {
            super(context, attributes);
            this.Init(context, attributes);
        }
        //================================================================================

        //================================================================================
        //==== protected methods
        protected void Init(Context context, AttributeSet attributes)
        {
            //---- inflate our layout
            LayoutInflater layoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            layoutInflater.inflate(R.drawable.controls_custombanner, this);

            this._banner = (ImageView)findViewById(R.id.imgBanner);

                // swipe detection on the image
             this.gestureDetector = new GestureDetector(new MyGestureDetector());
            this.gestureListener = new View.OnTouchListener() {
                    public boolean onTouch(View v, MotionEvent event) {
                        if (gestureDetector.onTouchEvent(event)) {
                            return true;
                        }
                        return false;
                    }
                };
                // leave this, it needs to be here in order to redirect the swipe correctly to touch gesture direction
               this._banner.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        // leave blank, click is redirected to gesture 
                    }
                }); 

             this._banner.setOnTouchListener(gestureListener);

                // set banner image
                this.setBanner(this.getCurrentIndexByWndId());
        }


        protected int getCurrentIndexByWndId() {

            // add your logic here
            // you need to access your state to get the last saved id
        }

        /**
         * this function does nothing but set the banner image by the position from the array of banners. 
         * */
        protected void setBanner(int position)
        {
            _banner.setImageResource(this.getBanners().get(position).ResourceId);
        }

        /**
         * this function tests the validity of the index in the banners array and resets it to 0 if its not valid.
         * */
        protected int checkValidIndex(int currentIndex){
            if (currentIndex > this.getBanners().size()-1)
                currentIndex = 0;
            return currentIndex;
        }

        protected void processBannerClick(Banner clickedBanner){
            try
            {
                // here do your logic for the click
            }
            catch (Exception ex)
            {
                Log.e(App.Current.getErrorTag(), ex.getMessage());
            }
        }

        //================================================================================

        //================================================================================
        //==== helper classes
        /**
         * this is a helper class to detect the gesture or swipe. It uses the onFling() to test whether it was a right or left swipe. 
         * It increments the position of and sets the appropriate next image on the banner.
         * */
        protected class MyGestureDetector extends SimpleOnGestureListener {
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                Log.i(TAG, "BANNER: onFling() happened");
                int currentIndex = 0;
                try {
                    currentIndex = FromState.getCurrentAdRotatorPosition();
                    if(isScrollingLeft(e1, e2)) {
                        // left swipe
                        if (currentIndex > 0)
                            currentIndex --;
                        else currentIndex = getBanners().size()-1;
                    }  
                    else {
                        // right swipe
                        if (currentIndex < getBanners().size()-1)
                            currentIndex ++;
                        else currentIndex = 0;
                    }
                } catch (Exception e) {
                    // do nothing
                }
                FromState..setCurrentAdRotatorPosition(currentIndex);
                setBanner(FromState.getCurrentAdRotatorPosition());
                return false;
            }

            @Override
            public boolean onSingleTapUp(MotionEvent ev)
            {
                Log.i(TAG, "BANNER: onSingleTapUp() happened");
                processBannerClick(getBanners().get(FromState.getCurrentAdRotatorPosition()));
                return false;
            }


            /** check if left swipe happened */
            private boolean isScrollingLeft(MotionEvent e1, MotionEvent e2){ 
                return e2.getX() > e1.getX(); 
           }
        }
        //================================================================================
    }

OTHER TIPS

http://permalink.gmane.org/gmane.comp.handhelds.android.devel/101327 This code may help you creating rotating onFling views. Just cut off useless functionality and you are nearly done. In order to remember the current banner you will probably have to create the banner class as a Singletone and then load it's instance and state to learn which banner is shown currently.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top