Android Custom Carousel Effect

  • 2021-12-13 17:03:13
  • OfStack

In this paper, we share the specific code of Android custom carousel effect for your reference. The specific contents are as follows

Overview

1. Write a layout with ViewPager, TextView and LinearLayout.

ViewPager: Used to carry pictures TextView: Used to display text descriptions LinearLayout: Used to show indicators

2. Customize ConstraintLayout, and handle page switching logic in this control.

Analysis

1. Get custom attributes and set some attributes


public BannerY(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    initView(context);
    initXmlParams(context, attrs, defStyleAttr);
    fixParams();
    initListener();
    initLists();
    initImageLoader();
}
/**
 *  Initialization ImageLoader
 */
private void initImageLoader() {
    ImageLoader.getInstance().init(ImageLoaderConfiguration.createDefault(mContext));
}
/**
 *  Fill the layout into the BannerY, Get VP,TextView,LinearLayout Control 
 *
 * @param context
 */
private void initView(Context context) {
    mContext = context;
    LayoutInflater.from(context).inflate(R.layout.layout_banner, this);
    mVp = (ViewPager) findViewById(R.id.vp);
    mTvDesc = (TextView) findViewById(R.id.tv_desc);
    mLLPoint = (LinearLayout) findViewById(R.id.ll_point);
}
/**
 *  Get custom properties 
 *
 * @param context
 * @param attrs
 * @param defStyleAttr
 */
private void initXmlParams(Context context, AttributeSet attrs, int defStyleAttr) {
    TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BannerY, defStyleAttr, 0);
    mPointSize = typedArray.getDimensionPixelSize(R.styleable.BannerY_point_size, 8);
    mPointBG = typedArray.getResourceId(R.styleable.BannerY_point_bg, R.drawable.point_selector);
    mInterval = typedArray.getInteger(R.styleable.BannerY_banner_interval, 2000);
    mTvBottomMargin = typedArray.getDimensionPixelSize(R.styleable.BannerY_desc_bottom_margin, 8);
    mPointBottomMargin = typedArray.getDimensionPixelSize(R.styleable.BannerY_point_bottom_margin, 8);
    mDescColor = typedArray.getColor(R.styleable.BannerY_desc_color, Color.BLACK);
    mDescSize = typedArray.getDimensionPixelSize(R.styleable.BannerY_desc_size, 14);
    mScaleType = typedArray.getInt(R.styleable.BannerY_banner_scaletype, -1);
    typedArray.recycle();
}
/**
 *  Adjust the pointer and text description position through custom properties 
 */
private void fixParams() {
    // Describe the control 
    LayoutParams mTvDescLayoutParams = (LayoutParams) mTvDesc.getLayoutParams();
    mTvDescLayoutParams.bottomMargin = (int) mTvBottomMargin;
    mTvDesc.setLayoutParams(mTvDescLayoutParams);
    mTvDesc.setTextColor(mDescColor);
    mTvDesc.getPaint().setTextSize(mDescSize);
    // Indicator 
    LayoutParams mLLPointLayoutParams = (LayoutParams) mLLPoint.getLayoutParams();
    mLLPointLayoutParams.bottomMargin = (int) mPointBottomMargin;
    mLLPoint.setLayoutParams(mLLPointLayoutParams);
}
/**
 *  Create a data source collection and create a Handler Object 
 */
@SuppressLint("HandlerLeak")
private void initLists() {
    mImageViewList = new ArrayList<>();
    mDescList = new ArrayList<>();
    mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            //  Get ViewPager Index value of the current display picture 
            int currentItem = mVp.getCurrentItem();
            //  Switch to below 1 Pictures 
            mVp.setCurrentItem(currentItem + 1);
            //  Interval 1 Send at a fixed time 1 Messages , The interval duration is controlled by custom attribute values .
            mHandler.sendEmptyMessageDelayed(1, mInterval);
        }
    };
}
/**
 *  For ViewPager Setting Slide Listening 
 */
private void initListener() {
    mVp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        }
        @Override
        public void onPageSelected(int position) {
            // ViewPager A total of Integer.MAX_VALUE Views 
            // position Mould taking , Convert to mImageViewList Corresponding index .
            int realPosition = position % mImageViewList.size();
            if (mDescList.size() == mImageViewList.size()) {
                //  The text description set is equal in length to the picture set , Then it is a text description TextView Show the corresponding text content .
                String desc = mDescList.get(realPosition);
                mTvDesc.setText(desc);
            } else {
                if (BuildConfig.DEBUG) {
                    Log.d(TAG, " Text collection and picture collection are not equal in length ");
                }
            }
            //  Upper 1 The indicator corresponding to the pages is set to unchecked 
            mLLPoint.getChildAt(prePosition).setEnabled(false);
            //  From the indicator-mounted LinearLayout Obtain the indicator corresponding to the current view in the , Then set the indicator to be currently selected , So as to change the color of the indicator .
            mLLPoint.getChildAt(realPosition).setEnabled(true);
            prePosition = realPosition;
        }
        @Override
        public void onPageScrollStateChanged(int state) {
            if (state == ViewPager.SCROLL_STATE_DRAGGING) {// Sliding 
                //  Manual touch ViewPager, So that it is in a sliding state ,Handler Stop sending messages .
                isDragging = true;
                mHandler.removeCallbacksAndMessages(null);
            }
            if (state == ViewPager.SCROLL_STATE_IDLE && isDragging) {// Idle state 
                // ViewPager After the manual sliding stops, , Re-open Handler Send a message .
                mHandler.removeCallbacksAndMessages(null);
                mHandler.sendEmptyMessageDelayed(1, mInterval);
            }
        }
    });
}

2. Set the picture source collection


/**
 *  Set up the picture source 
 * @param imagesRes
 * @param <T>
 */
public <T> void setImagesRes(ArrayList<T> imagesRes) {
    if (judgeLenght(imagesRes)) {
        mImageViewList.clear();
        //  Initialize the picture list 
        initImageList(imagesRes);
        //  Create Adapter
        mBannerAdapter = new BannerAdapter(mImageViewList);
        mVp.setAdapter(mBannerAdapter);
        //  Settings ViewPager The current view is in the middle position ,  Because ViewPager The number of views is Integer.MAX_VALUE( In ViewPagerAdapter Set in the ).
        int position = Integer.MAX_VALUE / 2 - Integer.MAX_VALUE / 2 % mImageViewList.size();
        //  Sets the current ViewPager Which view to show 
        mVp.setCurrentItem(position);
        //  Open a message loop 
        mHandler.sendEmptyMessageDelayed(1, mInterval);
        if (mDescList.size() == mImageViewList.size()) {
            //  Set up text description display 
            mTvDesc.setText(mDescList.get(prePosition));
        }
    }
}

/**
 *  Initialize the picture list 
 */
private void initImageList(ArrayList imagesRes) {
    Class<?> imageResClass = imagesRes.get(0).getClass();
    for (int i = 0; i < imagesRes.size(); i++) {
        //  Create ImageView
        ImageView imageView = createImageView(imagesRes, i, imageResClass);
        //  For ImageView Set click events 
        setImageViewListener(imageView);
        //  Will ImageView Add to the collection 
        mImageViewList.add(imageView);
        // Add an indicator 
        addPoint(i);
    }
}
/**
 *  Create from parameters ImageView Object 
 *
 * @param imagesRes
 * @param i
 * @param imageResClass
 * @return
 */
private ImageView createImageView(ArrayList imagesRes, int i, Class<?> imageResClass) {
    ImageView imageView = new ImageView(mContext);
    ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    imageView.setLayoutParams(layoutParams);
    ImageView.ScaleType scaleType = sScaleTypeArray[mScaleType];
    imageView.setScaleType(scaleType);
    if (imageResClass.equals(String.class)) {
        //  If the picture data source collection is url, Website picture 
        String url = (String) imagesRes.get(i);
        //  Use ImageLoader Show the picture to the ImageView Medium 
        ImageLoader.getInstance().displayImage(url, imageView);
    } else if (imageResClass.equals(Integer.class)) {
        //  If the picture data source collection is a picture resource ID
        Integer resId = (Integer) imagesRes.get(i);
        imageView.setImageResource(resId);
    }
    return imageView;
}

/**
 *  For ImageView Object sets click events and touch events 
 *
 * @param imageView
 */
@SuppressLint("ClickableViewAccessibility")
private void setImageViewListener(ImageView imageView) {
    imageView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    //  When the finger is in ImageView Press down , Then stop handler Send a message to switch pictures 
                    mHandler.removeCallbacksAndMessages(null);
                    break;
                case MotionEvent.ACTION_UP:
                    //  When your fingers are raised , Send the Switch Picture message normally .
                    mHandler.removeCallbacksAndMessages(null);
                    mHandler.sendEmptyMessageDelayed(1, mInterval);
                    break;
            }
            return false;
        }
    });
    imageView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (mIClickBanner != null) {
                //  When clicked ImageView Hour , Pass getTage() Gets the current view index value corresponding to the picture .
                //  The value is specified in the ViewPagerAdapter In instantiateItem() Set in the .
                int positon = (int) v.getTag();
                int i = positon % mImageViewList.size();
                mIClickBanner.click(i);
            } else {
                if (BuildConfig.DEBUG) {
                    Log.e(TAG, " Picture callback method is nonexistent ");
                }
            }
        }
    });
}

3. Adapter of BannerY


public class BannerAdapter<T> extends PagerAdapter {
    private final static String TAG = BannerAdapter.class.getName();
    ArrayList<ImageView> mImageViewList;
    /**
     * @param mImageViewList ImageView  Control list , In the list IamgeView Have set up picture resources and click events, etc. .
     */
    public BannerAdapter(ArrayList<ImageView> mImageViewList) {
        this.mImageViewList = mImageViewList;
    }
    @Override
    public int getCount() {
        //  Settings ViewPager Number of views of ,Integer.MAX_VALUE Yes 1 A very large number ,  No matter how long the polling is, it is difficult to reach the end .
        return Integer.MAX_VALUE;
    }
    @SuppressLint("ClickableViewAccessibility")
    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, final int position) {
        // position This number is very large ,  After taking the mold, it can correspond mImageViewList The index value in the collection is changed .
        final int realPosition = position % mImageViewList.size();
        ImageView imageView = mImageViewList.get(realPosition);
        //  Match the index value with the ImageView Binding , When clicked, the index value can be taken out .
        imageView.setTag(position);
        ViewParent viewParent = imageView.getParent();
        if (viewParent != null) {
            //  This is to prevent ViewPager Add pictures repeatedly .
            ((ViewGroup) viewParent).removeView(imageView);
        }
        //  Add a picture to the ViewPager Medium 
        container.addView(imageView);
        return imageView;
    }

    @Override
    public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
        return view == object;
    }

    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        
    }
}

Related articles: