Skip to content

Commit

Permalink
indicator flow
Browse files Browse the repository at this point in the history
  • Loading branch information
ymex committed Nov 17, 2017
1 parent d390a08 commit 452548c
Show file tree
Hide file tree
Showing 9 changed files with 256 additions and 31 deletions.
146 changes: 122 additions & 24 deletions banner/src/main/java/cn/ymex/widget/banner/IndicatorLayout.java
@@ -1,10 +1,14 @@
package cn.ymex.widget.banner;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
Expand All @@ -15,6 +19,7 @@
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
Expand All @@ -28,22 +33,28 @@

public class IndicatorLayout extends LinearLayout implements IndicatorAble {

private static final int DEF_SELECTED_COLOR = 0XFFFFFFFF;
private static final int DEF_UNSELECTED_COLOR = 0X88FFFFFF;

private Drawable mSelectedDrawable;
private Drawable mUnSelectedDrawable;
private static final int DEF_SELECTED_COLOR = 0XFFFFFFFF, DEF_UNSELECTED_COLOR = 0X88FFFFFF;
private Drawable mSelectedDrawable, mUnSelectedDrawable;

private int mIndicatorWidth;
private int mIndicatorHeight;
private int mIndicatorMargin;
private int mIndicatorCount;
private int mIndicatorShap;
private boolean mFlowIndicator;//指示器跟随

private boolean mIndicatorFlow;//指示器跟随
private View mFirstIndicator, mSecondIndicator;
private int mMoveDistance = 0;
private int mMarginSize;

private Paint mBitPaint;
private RectF mRectF;
private Rect mSrcRect;
private Bitmap mSelectBitmap;


private static int dip4 = dp2px(4);
private static int dip8 = dp2px(8);
private static int dip4 = (int) dp2px(4);
private static int dip8 = (int) dp2px(8);


public IndicatorLayout(Context context, int count) {
Expand Down Expand Up @@ -88,6 +99,8 @@ private void dealAttrs(AttributeSet attrs) {
mSelectedDrawable = typedArray.getDrawable(R.styleable.IndicatorLayout_indicator_selected);
mUnSelectedDrawable = typedArray.getDrawable(R.styleable.IndicatorLayout_indicator_unselected);

mIndicatorFlow = typedArray.getBoolean(R.styleable.IndicatorLayout_indicator_flow, false);

mIndicatorShap = typedArray.getInt(R.styleable.IndicatorLayout_indicator_shape, 0);


Expand Down Expand Up @@ -144,14 +157,18 @@ public void setIndicatorSpace(int indicatorSpace) {
this.mIndicatorMargin = indicatorSpace;
}

public static int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
Resources.getSystem().getDisplayMetrics());

public boolean isIndicatorFlow() {
return mIndicatorFlow;
}

@Override
public void onBannerScrolled(int position, float positionOffset, int positionOffsetPixels) {
public void setIndicatorFlow(boolean mIndicatorFlow) {
this.mIndicatorFlow = mIndicatorFlow;
}

public static float dp2px(float dp) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
Resources.getSystem().getDisplayMetrics());
}


Expand All @@ -162,11 +179,10 @@ public void onBannerScrollStateChanged(int state) {

@Override
public void onBannerSelected(int position, int size, Object object) {
if (!mFlowIndicator) {
if (mIndicatorFlow) {//跟随处理
} else {
changeIndicator(position);
return;
}
// TODO: 2017/11/16 指示器跟随处理
}

@Override
Expand All @@ -176,24 +192,33 @@ public void initIndicator(int size) {
if (size < 2) {
return;
}

for (int i = 0; i < mIndicatorCount; i++) {
AppCompatImageView imageView = new AppCompatImageView(getContext());
imageView.setScaleType(ImageView.ScaleType.FIT_XY);

LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
lp.rightMargin = lp.leftMargin = lp.topMargin = lp.bottomMargin = mIndicatorMargin;

if (mIndicatorWidth != dip8) {
lp.width = mIndicatorWidth;
}
if (mIndicatorHeight != dip8) {
lp.height = mIndicatorHeight;
}
if (mIndicatorWidth != dip8) lp.width = mIndicatorWidth;
if (mIndicatorHeight != dip8) lp.height = mIndicatorHeight;

imageView.setImageDrawable(mFlowIndicator ? mUnSelectedDrawable : i == 0 ? mSelectedDrawable : mUnSelectedDrawable);
imageView.setImageDrawable(mIndicatorFlow ? mUnSelectedDrawable : i == 0 ? mSelectedDrawable : mUnSelectedDrawable);

if (i == 0) mFirstIndicator = imageView;
if (i == 1) mSecondIndicator = imageView;
addView(imageView, lp);
}
initPaint();
mSelectBitmap = drawable2Bitmap(mSelectedDrawable);
mSrcRect = new Rect(0, 0, mSelectBitmap.getWidth(), mSelectBitmap.getHeight());
}

private void initPaint() {
mBitPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBitPaint.setFilterBitmap(true);
mBitPaint.setDither(true);
}

/**
Expand All @@ -208,14 +233,87 @@ public void changeIndicator(int currentIndex) {
}
}


@Override
public void onBannerScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (!mIndicatorFlow) {
return;
}
if (position == (mIndicatorCount - 1) && positionOffset > 0) {
if (positionOffset >= 50) {
mMoveDistance = 0;
}
} else {
mMoveDistance = (int) (positionOffset * mMarginSize + position % mIndicatorCount * mMarginSize);
}
postInvalidate();
}


@SuppressLint("DrawAllocation")
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (mFirstIndicator == null || mSecondIndicator == null) {
return;
}
int[] mFirstPos = new int[2];
int[] mSecondPos = new int[2];
int[] viewPos = new int[2];
mFirstIndicator.getLocationOnScreen(mFirstPos);
mSecondIndicator.getLocationOnScreen(mSecondPos);
getLocationInWindow(viewPos);

// 指示器间的距离
if (getOrientation() == HORIZONTAL) {
mMarginSize = mSecondPos[0] - mFirstPos[0];
} else {
mMarginSize = mSecondPos[1] - mFirstPos[1];
}
int firstIndicatorX = mFirstPos[0] - viewPos[0];
int firstIndicatorY = mFirstPos[1] - viewPos[1];

mRectF = new RectF(firstIndicatorX, firstIndicatorY,
firstIndicatorX + mSelectBitmap.getWidth(), firstIndicatorY + mSelectBitmap.getHeight());
}

@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (mIndicatorFlow) {
canvas.save();
if (getOrientation() == HORIZONTAL) {
canvas.translate(mMoveDistance, 0);
} else {
canvas.translate(0, mMoveDistance);
}
canvas.drawBitmap(mSelectBitmap, mSrcRect, mRectF, mBitPaint);
canvas.restore();
}
}


/**
* drawable to bitmap
*
* @param drawable drawable
* @return bitmap
*/
Bitmap drawable2Bitmap(Drawable drawable) {

Bitmap bitmap = Bitmap
.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(),
drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565);


//注意,若不使用canvas画入,在View或者SurfaceView里的canvas.drawBitmap会看不到图
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight());
drawable.draw(canvas);
return bitmap;
}

}
1 change: 1 addition & 0 deletions banner/src/main/res/values/attrs.xml
Expand Up @@ -15,6 +15,7 @@
<attr name="indicator_margin" format="dimension" />
<attr name="indicator_selected" format="color|reference" />
<attr name="indicator_unselected" format="color|reference" />
<attr name="indicator_flow" format="boolean" />
<attr name="indicator_shape" format="enum">
<enum name="circular" value="0" />
<enum name="rectangle" value="1" />
Expand Down
13 changes: 10 additions & 3 deletions sample/src/main/AndroidManifest.xml
Expand Up @@ -12,19 +12,26 @@
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity" />
<activity android:name=".DefaultBannerActivity" />
<activity android:name=".DefaultBannerActivity"></activity>
<activity android:name=".CustomBannerActivity" />
<activity android:name=".VerticalBannerActivity" />
<activity android:name=".AnimationBannerActivity" />
<activity android:name=".IndicatorBannerActivity" />
<activity android:name=".ListviewBannerActivity" />
<activity android:name=".FlowIndicatorBannerActivity">
<!--<intent-filter>-->
<!--<action android:name="android.intent.action.MAIN" />-->

<!--<category android:name="android.intent.category.LAUNCHER" />-->
<!--</intent-filter>-->
</activity>
<activity
android:name=".GuidePageActivity"
android:theme="@style/AppTheme.NoActionBar.FullPage">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".RecyclerBannerActivity">
Expand Down
@@ -0,0 +1,52 @@
package com.example.banner;

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

import com.bumptech.glide.Glide;
import com.example.banner.entity.BanneModel;
import com.example.banner.entity.DateBox;

import java.util.List;

import cn.ymex.kits.Finder;
import cn.ymex.widget.banner.Banner;
import cn.ymex.widget.banner.callback.BindViewCallBack;
import cn.ymex.widget.banner.callback.OnClickBannerListener;

public class FlowIndicatorBannerActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flow_banner_user);

Banner banner = Finder.build(this).find(R.id.banner);
Banner banner1 = Finder.find(this, R.id.banner2);
initBanner(banner);
initBanner(banner1);
}


private void initBanner(Banner banner) {

banner.bindView(new BindViewCallBack<AppCompatImageView, BanneModel>() {

@Override
public void bindView(AppCompatImageView view, BanneModel data, int position) {//图片处理
//使用glide 加载图片到 view组件,data 是你的数据 。
Glide.with(view.getContext()).load(data.getUrl()).into(view);
}

}).setOnClickBannerListener(new OnClickBannerListener<AppCompatImageView, BanneModel>() {

@Override
public void onClickBanner(AppCompatImageView view, BanneModel data, int position) {//点击事件
Toast.makeText(view.getContext(), "click position :" + position + "\n标题:" + data.getTitle(), Toast.LENGTH_SHORT).show();
}

}).execute(DateBox.banneModels());//填充数据
}
}
6 changes: 6 additions & 0 deletions sample/src/main/java/com/example/banner/MainActivity.java
Expand Up @@ -70,6 +70,12 @@ public void onClick(View v) {
startAction(DefaultBannerActivity.class.getName());
}
}));
add(new ItemActionModel("指示器跟随移动").setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startAction(FlowIndicatorBannerActivity.class.getName());
}
}));
add(new ItemActionModel("定制指示器").setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Expand Down
7 changes: 3 additions & 4 deletions sample/src/main/res/layout/activity_default_banner_user.xml
Expand Up @@ -13,16 +13,15 @@
android:layout_height="240dip"
android:background="#eeeeee"
app:banner_auto_play="true"
app:banner_interval="3000">
app:banner_interval="3000"
app:banner_orientation="vertical">

<cn.ymex.widget.banner.IndicatorLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginBottom="8dip"
android:gravity="center"
app:indicator_selected="@color/colorAccent"
app:indicator_shape="circular" />
android:gravity="center" />
</cn.ymex.widget.banner.Banner>

<TextView
Expand Down

0 comments on commit 452548c

Please sign in to comment.