自定义view之轮播图简单实现

直接copy的三个类
ABaseTransformer

/*
 * Copyright 2014 Toxic Bakery
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package view.zhengxiaolong.bw.com.myviewtextthree;


import android.support.v4.view.ViewPager.PageTransformer;
import android.view.View;


public abstract class ABaseTransformer implements PageTransformer {


/**
* Called each {@link #transformPage(View, float)}.
*
* @param page
*            Apply the transformation to this page
* @param position
*            Position of page relative to the current front-and-center position of the pager. 0 is front and
*            center. 1 is one full page position to the right, and -1 is one page position to the left.
*/
protected abstract void onTransform(View page, float position);


/**
* Apply a property transformation to the given page. For most use cases, this method should not be overridden.
* Instead use {@link #transformPage(View, float)} to perform typical transformations.
*
* @param page
*            Apply the transformation to this page
* @param position
*            Position of page relative to the current front-and-center position of the pager. 0 is front and
*            center. 1 is one full page position to the right, and -1 is one page position to the left.
*/
@Override
public void transformPage(View page, float position) {
onPreTransform(page, position);
onTransform(page, position);
onPostTransform(page, position);
}


/**
* If the position offset of a fragment is less than negative one or greater than one, returning true will set the
* fragment alpha to 0f. Otherwise fragment alpha is always defaulted to 1f.
*
* @return
*/
protected boolean hideOffscreenPages() {
return true;
}


/**
* Indicates if the default animations of the view pager should be used.
*
* @return
*/
protected boolean isPagingEnabled() {
return false;
}


/**
* Called each {@link #transformPage(View, float)} before {{@link #onTransform(View, float)}.
* <p>
* The default implementation attempts to reset all view properties. This is useful when toggling transforms that do
* not modify the same page properties. For instance changing from a transformation that applies rotation to a
* transformation that fades can inadvertently leave a fragment stuck with a rotation or with some degree of applied
* alpha.
*
* @param page
*            Apply the transformation to this page
* @param position
*            Position of page relative to the current front-and-center position of the pager. 0 is front and
*            center. 1 is one full page position to the right, and -1 is one page position to the left.
*/
protected void onPreTransform(View page, float position) {
final float width = page.getWidth();


page.setRotationX(0);
page.setRotationY(0);
page.setRotation(0);
page.setScaleX(1);
page.setScaleY(1);
page.setPivotX(0);
page.setPivotY(0);
page.setTranslationY(0);
page.setTranslationX(isPagingEnabled() ? 0f : -width * position);


if (hideOffscreenPages()) {
page.setAlpha(position <= -1f || position >= 1f ? 0f : 1f);
// page.setEnabled(false);
} else {
// page.setEnabled(true);
page.setAlpha(1f);
}
}


/**
* Called each {@link #transformPage(View, float)} after {@link #onTransform(View, float)}.
*
* @param page
*            Apply the transformation to this page
* @param position
*            Position of page relative to the current front-and-center position of the pager. 0 is front and
*            center. 1 is one full page position to the right, and -1 is one page position to the left.
*/
protected void onPostTransform(View page, float position) {
}


/**
* Same as {@link Math#min(double, double)} without double casting, zero closest to infinity handling, or NaN support.
*
* @param val
* @param min
* @return
*/
protected static final float min(float val, float min) {
return val < min ? min : val;
}


}


AccordionTransformer

/*
 * Copyright 2014 Toxic Bakery
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package view.zhengxiaolong.bw.com.myviewtextthree;


import android.view.View;


public class AccordionTransformer extends ABaseTransformer {


@Override
protected void onTransform(View view, float position) {
view.setPivotX(position < 0 ? 0 : view.getWidth());
view.setScaleX(position < 0 ? 1f + position : 1f - position);
}


}


AutoBanner

package view.zhengxiaolong.bw.com.myviewtextthree;


import android.content.Context;
import android.content.res.TypedArray;
import android.os.Handler;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;


import com.bumptech.glide.Glide;


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


/**
 * Created by kson on 2017/6/30.
 */


public class AutoBanner extends FrameLayout implements ViewPager.OnPageChangeListener {
    private static final String TAG = "AutoBanner";


    private Context mContext;
    private int mIndicatorWidth, mIndicatorHeight, mIndicatorMargin;
    private List<String> mImgUrls;
    private List<View> mImageViews;
    private List<ImageView> mIndicatorViews;
    private LinearLayout mIndicatorLayout;
    private ViewPager mViewPager;
    private AutoBannerListener mAutoBannerListener;
    private AutoBannerPagerAdapter mAutoBannerPagerAdapter;
    private int count;
    private float ratio = 1.78f;//图片宽高比




    //自动轮播
    private boolean isAuto;
    private Handler mAutoHandler = new Handler();
    private int currentItem;
    private int delayTime = 1000;




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


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


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


    private void init(Context context, AttributeSet attrs) {
        this.mContext = context;
        mImageViews = new ArrayList<>();
        mImgUrls = new ArrayList<>();
        mIndicatorViews = new ArrayList<>();
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AutoBanner);
        mIndicatorWidth = typedArray.getDimensionPixelSize(R.styleable.AutoBanner_indicator_width, 30);
        mIndicatorHeight = typedArray.getDimensionPixelSize(R.styleable.AutoBanner_indicator_height, 30);
        mIndicatorMargin = typedArray.getDimensionPixelSize(R.styleable.AutoBanner_indicator_margin, 10);


        ratio = typedArray.getFloat(R.styleable.AutoBanner_ratio_wh, 1.78f);


        typedArray.recycle();


        View view = LayoutInflater.from(context).inflate(R.layout.auto_banner_layout, this, true);
        mViewPager = (ViewPager) view.findViewById(R.id.banner_viewpager);
        mIndicatorLayout = (LinearLayout) view.findViewById(R.id.circleIndicator);




    }


    /**
     * 设置图片源
     *
     * @param imgs
     * @return
     */
    public AutoBanner load(List<String> imgs) {
        this.mImgUrls = imgs;
        this.count = mImgUrls.size();
        return this;
    }




    public AutoBanner setAuto(int time) {
        this.delayTime = time;
        this.isAuto = true;
        return this;
    }


    /**
     * 加载和显示banner
     *
     * @return
     */
    public AutoBanner display() {
        setImages();
        setIndicators();
        return this;
    }
    public AutoBanner setAnimation() {
        return this;
    }
    private void setImages() {
        if (count == 0) {
            return;
        }
        for (int i = 0; i < count; i++) {
            ImageView imageView = new ImageView(mContext);
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            mImageViews.add(imageView);
        }
        if (mAutoBannerPagerAdapter == null) {
            mAutoBannerPagerAdapter = new AutoBannerPagerAdapter();
            mViewPager.addOnPageChangeListener(this);
        }
        mViewPager.setAdapter(mAutoBannerPagerAdapter);
        mViewPager.setCurrentItem(0);
        if (isAuto) {
            startAuto();
        }
    }
    /**
     * 自动轮播
     */
    public void startAuto() {
        mAutoHandler.removeCallbacks(task);
        mAutoHandler.postDelayed(task, delayTime);

    }

    public void stopAuto() {
        mAutoHandler.removeCallbacks(task);
    }

    private final Runnable task = new Runnable() {
        @Override
        public void run() {
            if (count > 1 && isAuto) {
                if (currentItem >= count) {
                    currentItem = 0;
                }
                mViewPager.setCurrentItem(currentItem);
                mAutoHandler.postDelayed(task, delayTime);
                Log.i(TAG, "curr:" + currentItem + " count:" + count);
            }
        }
    };

    /**
     * 计算viewpager的宽高比,以便适配
     */
    private void initViewPagerParams() {
        ViewGroup.LayoutParams params = mViewPager.getLayoutParams();
        params.width = getMeasuredWidth();
        params.height = (int) (params.width / ratio);
        mViewPager.setLayoutParams(params);
    }

    private void setIndicators() {
        mIndicatorViews.clear();
        mIndicatorLayout.removeAllViews();
        if (count < 2) {//一个view时不绘制指示器
            return;
        }
        for (int i = 0; i < count; i++) {
            ImageView imageView = new ImageView(mContext);
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(mIndicatorWidth, mIndicatorHeight);
            layoutParams.leftMargin = mIndicatorMargin;
            layoutParams.rightMargin = mIndicatorMargin;
            if (i == 0) {
                imageView.setImageResource(R.drawable.indicator_selected);
            } else {
                imageView.setImageResource(R.drawable.indicator_unselect);
            }

            mIndicatorViews.add(imageView);

            mIndicatorLayout.addView(imageView, layoutParams);

        }
    }

    public AutoBanner setAutoBannerAnimation(Class<? extends ViewPager.PageTransformer> transformer) {
        try {
            setPageTransformer(true, transformer.newInstance());
        } catch (Exception e) {
            Log.e(TAG, "Please set the PageTransformer class");
        }
        return this;
    }

    /**
     * Set a {@link ViewPager.PageTransformer} that will be called for each attached page whenever
     * the scroll position is changed. This allows the application to apply custom property
     * transformations to each page, overriding the default sliding look and feel.
     *
     * @param reverseDrawingOrder true if the supplied PageTransformer requires page views
     *                            to be drawn from last to first instead of first to last.
     * @param transformer         PageTransformer that will modify each page's animation properties
     * @return Banner
     */
    public AutoBanner setPageTransformer(boolean reverseDrawingOrder, ViewPager.PageTransformer transformer) {
        mViewPager.setPageTransformer(reverseDrawingOrder, transformer);
        return this;
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        currentItem = position % count + 1;

    }

    @Override
    public void onPageSelected(int position) {
        for (int i = 0; i < count; i++) {
            if (i == position) {
                mIndicatorViews.get(i).setImageResource(R.drawable.indicator_selected);
            } else {
                mIndicatorViews.get(i).setImageResource(R.drawable.indicator_unselect);
            }
        }
    }
    @Override
    public void onPageScrollStateChanged(int state) {
    }

    class AutoBannerPagerAdapter extends PagerAdapter {
        @Override
        public int getCount() {
            return mImageViews.size();
        }

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

        @Override
        public Object instantiateItem(ViewGroup container, final int position) {
            container.addView(mImageViews.get(position));
            ImageView view = (ImageView) mImageViews.get(position);
            Glide.with(mContext).load(mImgUrls.get(position)).into(view);
            if (mAutoBannerListener != null) {
                view.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        mAutoBannerListener.onClickListener(position);
                    }
                });
            }
            return view;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }
    }

    public AutoBanner setOnAutoBannerListener(AutoBannerListener listener) {
        this.mAutoBannerListener = listener;
        return this;
    }
    public interface AutoBannerListener {
        void onClickListener(int postion);
    }
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        initViewPagerParams();
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (isAuto) {
            int action = ev.getAction();
            if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL
                    || action == MotionEvent.ACTION_OUTSIDE) {
                startAuto();
            } else if (action == MotionEvent.ACTION_DOWN) {
                stopAuto();
            }
        }
        return super.dispatchTouchEvent(ev);
    }

}


写到drawable的文件
indicator_selected

<?xml version="1.0" encoding="utf-8"?>

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid
        android:color="#5CB85C"/>
    <corners android:radius="5dip" />

</shape>

indicator_unselect

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid
        android:color="#999999"/>
    <corners android:radius="5dip" />
</shape>

copy到value的文件
attrs

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="AutoBanner">
        <attr name="indicator_width" format="dimension"></attr>
        <attr name="indicator_height" format="dimension"></attr>
        <attr name="indicator_margin" format="dimension"></attr>
        <attr name="ratio_wh" format="float"></attr>
    </declare-styleable>


    <declare-styleable name="ViewPagerIndicator">
        <attr name="item_count" format="integer" />
    </declare-styleable>
</resources>

copy到layout的布局文件
auto_banner_layout

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">


    <android.support.v4.view.ViewPager
        android:id="@+id/banner_viewpager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:visibility="visible"/>


    <LinearLayout
        android:id="@+id/circleIndicator"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:gravity="center"
        android:orientation="horizontal"
        android:padding="10dp" />


</FrameLayout>


写入自定义view的布局文件main_layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:autobanner="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent">


    <view.zhengxiaolong.bw.com.myviewtextthree.AutoBanner
        android:id="@+id/auto_banner"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        autobanner:indicator_height="10dp"
        autobanner:indicator_margin="10dp"
        autobanner:indicator_width="10dp"
        autobanner:ratio_wh="1.78"/>


</LinearLayout>


当前写入自定义view的Activity

MainActivity

package view.zhengxiaolong.bw.com.myviewtextthree;


import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;


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


public class MainActivity extends AppCompatActivity implements AutoBanner.AutoBannerListener {
    private AutoBanner mAutoBanner;
    private List<String> mImgUrls;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mAutoBanner = (AutoBanner) findViewById(R.id.auto_banner);
        mImgUrls = new ArrayList<>();


        mImgUrls.add("http://pic.58pic.com/58pic/13/61/00/61a58PICtPr_1024.jpg");
        mImgUrls.add("http://www.bz55.com/uploads/allimg/150525/139-150525111037.jpg");
        mImgUrls.add("http://www.bz55.com/uploads/allimg/141226/139-141226142542-50.jpg");
        //不设置setAuto,不会自动轮播,不设置监听,无法点击,动画转换器可以根据需要设置
        mAutoBanner.load(mImgUrls).setOnAutoBannerListener(this).setAuto(3000).setAutoBannerAnimation(AccordionTransformer.class).display();
    }
    @Override
    public void onClickListener(int postion) {
        Toast.makeText(MainActivity.this, "点击了:" + postion + "位置", Toast.LENGTH_SHORT).show();
    }
    @Override
    protected void onStart() {
        super.onStart();
        mAutoBanner.startAuto();
    }
    @Override
    protected void onStop() {
        super.onStop();
        mAutoBanner.stopAuto();
    }
    }



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值