com.tmall.wireless.tangram.view.BannerView.java Source code

Java tutorial

Introduction

Here is the source code for com.tmall.wireless.tangram.view.BannerView.java

Source

/*
 * MIT License
 *
 * Copyright (c) 2017 Alibaba Group
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package com.tmall.wireless.tangram.view;

import com.alibaba.android.vlayout.VirtualLayoutManager;
import com.tmall.ultraviewpager.UltraViewPager;
import com.tmall.wireless.tangram.core.R;
import com.tmall.wireless.tangram.core.adapter.BinderViewHolder;
import com.tmall.wireless.tangram.core.adapter.GroupBasicAdapter;
import com.tmall.wireless.tangram.dataparser.concrete.Style;
import com.tmall.wireless.tangram.structure.BaseCell;
import com.tmall.wireless.tangram.structure.cell.BannerCell;
import com.tmall.wireless.tangram.structure.view.ITangramViewLifeCycle;
import com.tmall.wireless.tangram.util.ImageUtils;
import com.tmall.wireless.tangram.util.Utils;

import android.content.Context;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Pair;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by mikeafc on 16/1/14.
 */
public class BannerView extends RelativeLayout implements ViewPager.OnPageChangeListener, ITangramViewLifeCycle {
    public static final int GRAVITY_LEFT = 0;
    public static final int GRAVITY_CENTER = 1;
    public static final int GRAVITY_RIGHT = 2;

    private UltraViewPager mUltraViewPager;
    private BannerIndicator mIndicator;
    private LayoutParams mIndicatorLayoutParams;

    private int mIndicatorHeight = ViewGroup.LayoutParams.WRAP_CONTENT;
    private int mIndicatorGap = Style.dp2px(6);
    private int mIndicatorMargin = Style.dp2px(10);

    private float xDown;
    private float yDown;

    private BaseCell cell;

    private List<BinderViewHolder> mViewHolders = new ArrayList<BinderViewHolder>();

    public BannerView(Context context) {
        this(context, null);
    }

    public BannerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BannerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mUltraViewPager = new UltraViewPager(getContext());
        mUltraViewPager.setId(R.id.TANGRAM_BANNER_ID);
        mIndicator = new BannerIndicator(getContext());
        addView(mUltraViewPager);
        addView(mIndicator, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT));

        mIndicatorLayoutParams = (LayoutParams) mIndicator.getLayoutParams();
        mIndicatorLayoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.TANGRAM_BANNER_ID);
        mIndicator.setPadding(mIndicatorGap, 0, 0, 0);
    }

    public void setAdapter(PagerAdapter adapter) {
        mUltraViewPager.setAdapter(adapter);
        mUltraViewPager.setOnPageChangeListener(this);
    }

    public void updateIndicators(String focusUrl, String norUrl, int radius, int focusColor, int norColor) {
        if (mIndicator != null) {
            mIndicator.updateIndicators(focusUrl, norUrl, radius, focusColor, norColor);
        }
    }

    public void setIndicatorGravity(int gravity) {
        switch (gravity) {
        case GRAVITY_LEFT:
            if (mIndicator != null) {
                mIndicator.setGravity(Gravity.LEFT);
            }
            break;
        case GRAVITY_CENTER:
            if (mIndicator != null) {
                mIndicator.setGravity(Gravity.CENTER_HORIZONTAL);
            }
            break;
        case GRAVITY_RIGHT:
            if (mIndicator != null) {
                mIndicator.setGravity(Gravity.RIGHT);
            }
            break;
        }
    }

    public void setIndicatorPos(String isInside) {
        if ("inside".equals(isInside)) {
            if (Build.VERSION.SDK_INT >= 17) {
                mIndicatorLayoutParams.removeRule(RelativeLayout.BELOW);
            }
            mIndicatorLayoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.TANGRAM_BANNER_ID);
        } else if ("outside".equals(isInside)) {
            if (Build.VERSION.SDK_INT >= 17) {
                mIndicatorLayoutParams.removeRule(RelativeLayout.ALIGN_BOTTOM);
            }
            mIndicatorLayoutParams.addRule(RelativeLayout.BELOW, R.id.TANGRAM_BANNER_ID);
        } else {
            if (Build.VERSION.SDK_INT >= 17) {
                mIndicatorLayoutParams.removeRule(RelativeLayout.BELOW);
            }
            mIndicatorLayoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.TANGRAM_BANNER_ID);
        }
    }

    public void setIndicatorGap(int gap) {
        if (gap > 0) {
            this.mIndicatorGap = gap;
        }
    }

    public void setIndicatorMargin(int indicatorMargin) {
        if (indicatorMargin > 0)
            this.mIndicatorMargin = indicatorMargin;
    }

    public void setIndicatorHeight(int indicatorHeight) {
        if (indicatorHeight > 0) {
            mIndicatorHeight = indicatorHeight;
        } else {
            mIndicatorHeight = ViewGroup.LayoutParams.WRAP_CONTENT;
        }
    }

    public UltraViewPager getUltraViewPager() {
        return mUltraViewPager;
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        mIndicator.setCurrItem(mUltraViewPager.getCurrentItem());
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }

    @Override
    public void cellInited(BaseCell cell) {
        this.cell = cell;
    }

    @Override
    public void postBindView(BaseCell cell) {
        BannerCell bannerCell = (BannerCell) cell;
        bannerCell.initAdapter();

        if (cell.style != null)
            setPadding(cell.style.padding[3], cell.style.padding[0], cell.style.padding[1], cell.style.padding[2]);

        setBackgroundColor(bannerCell.mBgColor);
        setAdapter(bannerCell.mBannerAdapter);
        getUltraViewPager().setAutoMeasureHeight(true);
        getUltraViewPager().setRatio(bannerCell.mRatio);
        getUltraViewPager().setAutoScroll(bannerCell.mAutoScrollInternal);
        getUltraViewPager().getViewPager().setPageMargin(bannerCell.hGap);
        if (bannerCell.mCells.size() <= bannerCell.mInfiniteMinCount) {
            getUltraViewPager().setInfiniteLoop(false);
        } else {
            getUltraViewPager().setInfiniteLoop(bannerCell.mInfinite);
        }
        setIndicatorGravity(getIndicatorGravity(bannerCell.mIndicatorGravity));
        setIndicatorPos(bannerCell.mIndicatorPos);
        int indicatorGap = bannerCell.mIndicatorGap;
        if (indicatorGap <= 0) {
            indicatorGap = mIndicatorGap;
        }
        setIndicatorGap(indicatorGap);
        int indicatorMargin = bannerCell.mIndicatorMargin;
        if (indicatorMargin <= 0) {
            indicatorMargin = mIndicatorMargin;
        }
        setIndicatorMargin(indicatorMargin);
        int indicatorHeight = bannerCell.mIndicatorHeight;
        setIndicatorHeight(indicatorHeight);
        if (bannerCell.itemMargin[0] > 0 || bannerCell.itemMargin[1] > 0) {
            getUltraViewPager().setScrollMargin(bannerCell.itemMargin[0], bannerCell.itemMargin[1]);
            getUltraViewPager().getViewPager().setClipToPadding(false);
            getUltraViewPager().getViewPager().setClipChildren(false);
        } else {
            getUltraViewPager().setScrollMargin(0, 0);
            getUltraViewPager().getViewPager().setClipToPadding(true);
            getUltraViewPager().getViewPager().setClipChildren(true);
        }

        VirtualLayoutManager.LayoutParams layoutParams = (VirtualLayoutManager.LayoutParams) getLayoutParams();
        layoutParams.setMargins(bannerCell.margin[3], bannerCell.margin[0], bannerCell.margin[1],
                bannerCell.margin[2]);

        updateIndicators(bannerCell.mIndicatorFocus, bannerCell.mIndicatorNor, bannerCell.mIndicatorRadius,
                bannerCell.mIndicatorColor, bannerCell.mIndicatorDefaultColor);
        recycleView();
        bindHeaderView(bannerCell.mHeader);
        bindFooterView(bannerCell.mFooter);
    }

    @Override
    public void postUnBindView(BaseCell cell) {
        recycleView();
    }

    private int getIndicatorGravity(String gravity) {
        if ("left".equals(gravity))
            return BannerView.GRAVITY_LEFT;
        if ("right".equals(gravity))
            return BannerView.GRAVITY_RIGHT;
        return BannerView.GRAVITY_CENTER;
    }

    class BannerIndicator extends LinearLayout {

        private final int STYLE_NONE = 0;
        private final int STYLE_DOT = 1;
        private final int STYLE_IMG = 2;

        private ImageView[] mImageViews;
        private String focusUrl;
        private String norUrl;
        private int norColor;
        private int focusColor;
        private float radius;
        private int style;

        public BannerIndicator(Context context) {
            super(context);
        }

        public void updateIndicators(String focusUrl, String norUrl, int radius, int focusColor, int norColor) {
            if (mUltraViewPager.getAdapter() == null)
                return;

            this.focusUrl = focusUrl;
            this.norUrl = norUrl;

            this.norColor = norColor;
            this.focusColor = focusColor;
            this.radius = radius;

            if (norColor != 0 && focusColor != 0 && radius > 0) {
                style = STYLE_DOT;
            } else if (!TextUtils.isEmpty(focusUrl) && !TextUtils.isEmpty(norUrl)) {
                style = STYLE_IMG;
            } else {
                style = STYLE_NONE;
            }
            if (style == STYLE_NONE) {
                setVisibility(INVISIBLE);
                return;
            } else {
                setVisibility(VISIBLE);
            }
            int width = 0;
            int height = 0;

            if (style == STYLE_IMG) {
                Pair<Integer, Integer> norSize = Utils.getImageSize(norUrl);
                Pair<Integer, Integer> focSize = Utils.getImageSize(focusUrl);
                if (norSize != null && focSize != null) {
                    width = Math.max(norSize.first, focSize.first);
                    height = Math.max(norSize.second, focSize.second);
                } else {
                    if (focSize != null) {
                        width = focSize.first;
                        height = focSize.second;
                    }
                    if (norSize != null) {
                        width = norSize.first;
                        height = norSize.second;
                    }
                }
            } else if (style == STYLE_DOT) {
                width = 2 * radius;
                height = 2 * radius;
            }
            if (mIndicatorHeight != ViewGroup.LayoutParams.WRAP_CONTENT && mIndicatorHeight > 0) {
                height = mIndicatorHeight;
            }

            int count = mUltraViewPager.getAdapter().getCount();
            if (mImageViews == null) {
                mImageViews = new ImageView[count];
                for (int i = 0; i < mImageViews.length; i++) {
                    mImageViews[i] = ImageUtils.createImageInstance(getContext());
                    mImageViews[i].setScaleType(ImageView.ScaleType.CENTER_INSIDE);
                    addView(mImageViews[i]);
                }
            } else if (mImageViews.length != count) {
                for (int i = 0; i < mImageViews.length; i++) {
                    removeView(mImageViews[i]);
                }
                ImageView[] old = mImageViews;
                mImageViews = new ImageView[count];
                System.arraycopy(old, 0, mImageViews, 0, Math.min(old.length, count));
                for (int i = 0; i < mImageViews.length; i++) {
                    if (mImageViews[i] == null) {
                        mImageViews[i] = ImageUtils.createImageInstance(getContext());
                        mImageViews[i].setScaleType(ImageView.ScaleType.CENTER_INSIDE);
                    }
                    addView(mImageViews[i]);
                }
            }
            int position = mUltraViewPager.getCurrentItem();
            for (int i = 0; i < mImageViews.length; i++) {
                LinearLayout.LayoutParams layoutParams = (LayoutParams) mImageViews[i].getLayoutParams();
                if (style == STYLE_IMG || style == STYLE_DOT) {
                    layoutParams.setMargins(0, mIndicatorMargin, mIndicatorGap, mIndicatorMargin);
                    if (width > 0)
                        layoutParams.width = width;
                    if (height > 0)
                        layoutParams.height = height;
                } else {
                    layoutParams.setMargins(0, 0, 0, 0);
                }
                if (style == STYLE_DOT) {
                    mImageViews[i]
                            .setImageDrawable(getGradientDrawable(position == i ? focusColor : norColor, radius));
                } else if (style == STYLE_IMG) {
                    ImageUtils.doLoadImageUrl(mImageViews[i], position == i ? focusUrl : norUrl);
                }
            }
        }

        public void setCurrItem(int position) {
            if (mImageViews != null) {
                for (int i = 0; i < mImageViews.length; i++) {
                    if (style == STYLE_DOT) {
                        mImageViews[i].setImageDrawable(
                                getGradientDrawable(position == i ? focusColor : norColor, radius));
                    } else if (style == STYLE_IMG) {
                        ImageUtils.doLoadImageUrl(mImageViews[i], position == i ? focusUrl : norUrl);
                    }
                }
            }
        }

        private GradientDrawable getGradientDrawable(int color, float radius) {
            GradientDrawable gradientDrawable = new GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP,
                    new int[] { color, color });
            gradientDrawable.setShape(GradientDrawable.OVAL);
            gradientDrawable.setCornerRadius(radius);
            return gradientDrawable;
        }

    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {

        int action = ev.getAction();
        float x = ev.getRawX();
        float y = ev.getRawY();

        switch (action) {
        case MotionEvent.ACTION_DOWN:
            xDown = x;
            yDown = y;
            break;
        case MotionEvent.ACTION_MOVE:
            int xDiff = (int) (x - xDown);
            int yDiff = (int) (y - yDown);
            //y?x?
            if (Math.abs(xDiff) >= Math.abs(yDiff)) {
                getParent().requestDisallowInterceptTouchEvent(true);
            } else {
                getParent().requestDisallowInterceptTouchEvent(false);
            }
            break;
        }

        return false;
    }

    private void bindHeaderView(BaseCell cell) {
        if (cell != null) {
            View header = getViewFromRecycler(cell);
            if (header != null) {
                header.setId(R.id.TANGRAM_BANNER_HEADER_ID);
                RelativeLayout.LayoutParams bodyLp = (LayoutParams) mUltraViewPager.getLayoutParams();
                bodyLp.addRule(RelativeLayout.BELOW, R.id.TANGRAM_BANNER_HEADER_ID);
                // item ?itemView  layoutParams ?? layout ,??? layoutParams
                RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                lp.topMargin = cell.style.margin[Style.MARGIN_TOP_INDEX];
                lp.leftMargin = cell.style.margin[Style.MARGIN_LEFT_INDEX];
                lp.bottomMargin = cell.style.margin[Style.MARGIN_BOTTOM_INDEX];
                lp.rightMargin = cell.style.margin[Style.MARGIN_RIGHT_INDEX];
                addView(header, lp);
            }
        }
    }

    private void bindFooterView(BaseCell cell) {
        if (cell != null) {
            View footer = getViewFromRecycler(cell);
            if (footer != null) {
                footer.setId(R.id.TANGRAM_BANNER_FOOTER_ID);
                // item ?itemView  layoutParams ?? layout ,??? layoutParams
                RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                lp.addRule(RelativeLayout.BELOW, R.id.TANGRAM_BANNER_ID);
                lp.topMargin = cell.style.margin[Style.MARGIN_TOP_INDEX];
                lp.leftMargin = cell.style.margin[Style.MARGIN_LEFT_INDEX];
                lp.bottomMargin = cell.style.margin[Style.MARGIN_BOTTOM_INDEX];
                lp.rightMargin = cell.style.margin[Style.MARGIN_RIGHT_INDEX];
                addView(footer, lp);
            }
        }
    }

    private View getViewFromRecycler(@NonNull BaseCell cell) {
        GroupBasicAdapter adapter = cell.serviceManager.getService(GroupBasicAdapter.class);
        RecyclerView.RecycledViewPool pool = cell.serviceManager.getService(RecyclerView.RecycledViewPool.class);
        int itemViewType = adapter.getItemType(cell);
        BinderViewHolder holder = (BinderViewHolder) pool.getRecycledView(itemViewType);
        if (holder == null) {
            holder = (BinderViewHolder) adapter.createViewHolder(this, itemViewType);
        }
        holder.bind(cell);
        mViewHolders.add(holder);
        return holder.itemView;
    }

    private void recycleView() {
        if (!mViewHolders.isEmpty()) {
            RecyclerView.RecycledViewPool pool = cell.serviceManager
                    .getService(RecyclerView.RecycledViewPool.class);
            for (int i = 0, size = mViewHolders.size(); i < size; i++) {
                BinderViewHolder viewHolder = mViewHolders.get(i);
                viewHolder.unbind();
                removeView(viewHolder.itemView);
                pool.putRecycledView(viewHolder);
            }
            mViewHolders.clear();
        }
    }

}