直接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();
}
}