recycleview 指示器
This commit is contained in:
@@ -118,7 +118,6 @@ object OverlayLeftViewUtils {
|
||||
if(taxiPassengerMogoConsultView?.get() != null){
|
||||
OverlayViewUtils.showOverlayView(context,taxiPassengerMogoConsultView?.get())
|
||||
}else{
|
||||
ToastUtils.showLong("已经回收")
|
||||
taxiPassengerMogoConsultView =
|
||||
WeakReference<TaxiPassengerMogoConsultView>(TaxiPassengerMogoConsultView(context))
|
||||
OverlayViewUtils.showOverlayView(context,taxiPassengerMogoConsultView?.get())
|
||||
@@ -135,7 +134,6 @@ object OverlayLeftViewUtils {
|
||||
if(taxiPassengerMogoMoviesView?.get() != null){
|
||||
OverlayViewUtils.showOverlayView(context,taxiPassengerMogoMoviesView?.get())
|
||||
}else{
|
||||
ToastUtils.showLong("已经回收")
|
||||
taxiPassengerMogoMoviesView =
|
||||
WeakReference<TaxiPassengerMogoMoviesView>(TaxiPassengerMogoMoviesView(context))
|
||||
OverlayViewUtils.showOverlayView(context,taxiPassengerMogoMoviesView?.get())
|
||||
|
||||
@@ -2,10 +2,10 @@ package com.mogo.och.taxi.passenger.ui.video
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
@@ -20,12 +20,16 @@ import com.mogo.och.taxi.passenger.bean.TaxiPassengerVideoPlay
|
||||
import com.mogo.och.taxi.passenger.ui.video.layoutmanage.CarouselLayoutManager
|
||||
import com.mogo.och.taxi.passenger.ui.video.layoutmanage.CarouselZoomPostLayoutListener
|
||||
import com.mogo.och.taxi.passenger.ui.video.layoutmanage.CenterScrollListener
|
||||
import com.mogo.och.taxi.passenger.widget.ConsultVideoPlayer
|
||||
import com.mogo.och.taxi.passenger.utils.blur.GlideBlurTransform
|
||||
import com.mogo.och.taxi.passenger.widget.ConsultVideoPlayer
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.IndicatorView
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorOrientation
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorSlideMode
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorStyle
|
||||
import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack
|
||||
import com.shuyu.gsyvideoplayer.video.base.GSYVideoView
|
||||
import io.reactivex.disposables.Disposable
|
||||
import java.util.*
|
||||
import kotlin.math.floor
|
||||
|
||||
|
||||
/**
|
||||
@@ -45,33 +49,38 @@ class TaxiPassengerMogoConsultView :RelativeLayout {
|
||||
|
||||
|
||||
private lateinit var rvVideoPlaylist: RecyclerView
|
||||
private lateinit var indicatorView: IndicatorView
|
||||
private lateinit var clContain: ConstraintLayout
|
||||
|
||||
private fun initView(context: Context) {
|
||||
d(SceneConstant.M_TAXI_P + "pageStopCenterScrollListener", "initView:$visibility")
|
||||
d(SceneConstant.M_TAXI_P + TAG, "initView")
|
||||
LayoutInflater.from(context).inflate(R.layout.taxi_p_arrived_mogo_consult, this, true)
|
||||
rvVideoPlaylist = findViewById(R.id.rv_video_playlist)
|
||||
indicatorView = findViewById(R.id.indicatorView)
|
||||
clContain = findViewById(R.id.cl_contain)
|
||||
|
||||
val arrayListOf = ArrayList<TaxiPassengerVideoPlay>()
|
||||
arrayListOf.add(TaxiPassengerVideoPlay("https://img.zhidaohulian.com/fileServer/online_car_hailing/1655708409810/20210610重新排版3屏.m4v","https://gohome-1253308323.cos.ap-beijing.myqcloud.com/McTk51586843620689.png","重新排版"))
|
||||
arrayListOf.add(TaxiPassengerVideoPlay("https://img.zhidaohulian.com/fileServer/online_car_hailing/1655708499497/大运会合作解说版.m4v","https://gohome-1253308323.cos.ap-beijing.myqcloud.com/12111.jpg","大运会合作解说"))
|
||||
arrayListOf.add(TaxiPassengerVideoPlay("https://img.zhidaohulian.com/fileServer/online_car_hailing/1655708554279/红旗车队.m4v","https://gohome-1253308323.cos.ap-beijing.myqcloud.com/McTk51586843620689.png","红旗车队"))
|
||||
arrayListOf.add(TaxiPassengerVideoPlay("https://img.zhidaohulian.com/fileServer/online_car_hailing/1655708596763/全车型混剪增加红旗车队.m4v","https://gohome-1253308323.cos.ap-beijing.myqcloud.com/12111.jpg","全车型混剪增加红旗车队"))
|
||||
arrayListOf.add(TaxiPassengerVideoPlay("https://img.zhidaohulian.com/fileServer/online_car_hailing/1655708499497/大运会合作解说版.m4v","https://gohome-1253308323.cos.ap-beijing.myqcloud.com/12111.jpg","大运会合作解说"))
|
||||
arrayListOf.add(TaxiPassengerVideoPlay("https://img.zhidaohulian.com/fileServer/online_car_hailing/1655708596763/全车型混剪增加红旗车队.m4v","https://gohome-1253308323.cos.ap-beijing.myqcloud.com/12111.jpg","全车型混剪增加红旗车队"))
|
||||
arrayListOf.add(TaxiPassengerVideoPlay("https://img.zhidaohulian.com/fileServer/online_car_hailing/1655708409810/20210610重新排版3屏.m4v","https://img.zhidaohulian.com/fileServer/online_car_hailing/1655969579713/三屏.png","重新排版"))
|
||||
arrayListOf.add(TaxiPassengerVideoPlay("https://img.zhidaohulian.com/fileServer/online_car_hailing/1655708499497/大运会合作解说版.m4v","https://img.zhidaohulian.com/fileServer/online_car_hailing/1655969536177/大运会.png","大运会"))
|
||||
arrayListOf.add(TaxiPassengerVideoPlay("https://img.zhidaohulian.com/fileServer/online_car_hailing/1655708554279/红旗车队.m4v","https://img.zhidaohulian.com/fileServer/online_car_hailing/1655969553174/红旗重新排版.png","红旗车队"))
|
||||
arrayListOf.add(TaxiPassengerVideoPlay("https://img.zhidaohulian.com/fileServer/online_car_hailing/1655708596763/全车型混剪增加红旗车队.m4v","https://img.zhidaohulian.com/fileServer/online_car_hailing/1655969511280/车队.png","全车型混剪增加红旗车队"))
|
||||
val recyclerVideoAdapter = RecyclerVideoAdapter(context, arrayListOf)
|
||||
val carouselLayoutManager = CarouselLayoutManager(CarouselLayoutManager.HORIZONTAL, true)
|
||||
carouselLayoutManager.setPostLayoutListener(CarouselZoomPostLayoutListener ())
|
||||
carouselLayoutManager.maxVisibleItems = 1
|
||||
indicatorView.notifyDataChanged(arrayListOf.size)
|
||||
indicatorView.setSlideMode(IndicatorSlideMode.SCALE)
|
||||
indicatorView.setOrientation(IndicatorOrientation.INDICATOR_HORIZONTAL)
|
||||
indicatorView.setIndicatorStyle(IndicatorStyle.ROUND_RECT)
|
||||
indicatorView.setSliderColor(Color.parseColor("#80FFFFFF"), Color.parseColor("#2972FF"))
|
||||
indicatorView.setSliderWidth(14f, 90f)
|
||||
indicatorView.setSliderHeight(14f)
|
||||
rvVideoPlaylist.addOnScrollListener(object: CenterScrollListener() {
|
||||
var prePlayerPosition = 0
|
||||
override fun pageSelect(recyclerView: RecyclerView?, newState: Int) {
|
||||
//播放视频
|
||||
val centerItemPosition: Int = carouselLayoutManager.centerItemPosition
|
||||
System.err.println("CarouselZoomPostLayoutListener---centerItemPosition:"+centerItemPosition+"----prePlayerPosition:"+prePlayerPosition);
|
||||
val player = carouselLayoutManager.findViewByPosition(centerItemPosition)
|
||||
indicatorView.onPageSelected(centerItemPosition)
|
||||
if(player is ConsultVideoPlayer){
|
||||
if(prePlayerPosition!=centerItemPosition) {
|
||||
if(player.currentState==GSYVideoView.CURRENT_STATE_PAUSE){
|
||||
@@ -98,6 +107,18 @@ class TaxiPassengerMogoConsultView :RelativeLayout {
|
||||
}
|
||||
|
||||
})
|
||||
carouselLayoutManager.addOnDargAutoDiffListener { adapterPosition, currentPosition ->
|
||||
val fl = adapterPosition - floor(adapterPosition)
|
||||
var currentIndex = currentPosition
|
||||
if(fl>0.5){
|
||||
if(currentPosition==0){
|
||||
currentIndex = rvVideoPlaylist.adapter!!.itemCount
|
||||
}else {
|
||||
currentIndex -= 1
|
||||
}
|
||||
}
|
||||
indicatorView.onPageScrolled(currentIndex, fl, 0)
|
||||
}
|
||||
rvVideoPlaylist.layoutManager = carouselLayoutManager
|
||||
rvVideoPlaylist.setHasFixedSize(true)
|
||||
rvVideoPlaylist.adapter = recyclerVideoAdapter
|
||||
@@ -128,20 +149,21 @@ class TaxiPassengerMogoConsultView :RelativeLayout {
|
||||
clContain.background = BitmapDrawable(context.resources, resource)
|
||||
}
|
||||
})
|
||||
|
||||
player.setVideoAllCallBack(object : GSYSampleCallBack() {
|
||||
override fun onAutoComplete(url: String?, vararg objects: Any?) {
|
||||
player.onVideoReset()
|
||||
val itemCount = rvVideoPlaylist.adapter?.itemCount
|
||||
itemCount?.let {
|
||||
if (centerItemPosition == itemCount - 1) {
|
||||
rvVideoPlaylist.smoothScrollToPosition(0)
|
||||
} else {
|
||||
rvVideoPlaylist.smoothScrollToPosition(centerItemPosition + 1)
|
||||
if(player.getVideoAllCallBack()==null) {
|
||||
player.setVideoAllCallBack(object : GSYSampleCallBack() {
|
||||
override fun onAutoComplete(url: String?, vararg objects: Any?) {
|
||||
player.onVideoReset()
|
||||
val itemCount = rvVideoPlaylist.adapter?.itemCount
|
||||
itemCount?.let {
|
||||
if (centerItemPosition == itemCount - 1) {
|
||||
rvVideoPlaylist.smoothScrollToPosition(0)
|
||||
} else {
|
||||
rvVideoPlaylist.smoothScrollToPosition(centerItemPosition + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -195,10 +217,9 @@ class TaxiPassengerMogoConsultView :RelativeLayout {
|
||||
val carouselLayoutManager = rvVideoPlaylist.layoutManager as CarouselLayoutManager
|
||||
val centerItemPosition: Int = carouselLayoutManager.centerItemPosition
|
||||
val player = carouselLayoutManager.findViewByPosition(centerItemPosition)
|
||||
d(SceneConstant.M_TAXI_P + "pageStopCenterScrollListener", "onDetachedFromWindow:$visibility---$player---${centerItemPosition}")
|
||||
player?.let {
|
||||
if(player is ConsultVideoPlayer){
|
||||
player.onVideoReset()
|
||||
player.release()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
package com.mogo.och.taxi.passenger.ui.video.layoutmanage;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public abstract class CarouselChildSelectionListener {
|
||||
|
||||
@NonNull
|
||||
private final RecyclerView mRecyclerView;
|
||||
@NonNull
|
||||
private final CarouselLayoutManager mCarouselLayoutManager;
|
||||
|
||||
private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
final RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
|
||||
final int position = holder.getAdapterPosition();
|
||||
|
||||
if (position == mCarouselLayoutManager.getCenterItemPosition()) {
|
||||
onCenterItemClicked(mRecyclerView, mCarouselLayoutManager, v);
|
||||
} else {
|
||||
onBackItemClicked(mRecyclerView, mCarouselLayoutManager, v);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
protected CarouselChildSelectionListener(@NonNull final RecyclerView recyclerView, @NonNull final CarouselLayoutManager carouselLayoutManager) {
|
||||
mRecyclerView = recyclerView;
|
||||
mCarouselLayoutManager = carouselLayoutManager;
|
||||
|
||||
mRecyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
|
||||
@Override
|
||||
public void onChildViewAttachedToWindow(@NonNull final View view) {
|
||||
view.setOnClickListener(mOnClickListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChildViewDetachedFromWindow(@NonNull final View view) {
|
||||
view.setOnClickListener(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected abstract void onCenterItemClicked(@NonNull final RecyclerView recyclerView, @NonNull final CarouselLayoutManager carouselLayoutManager, @NonNull final View v);
|
||||
|
||||
protected abstract void onBackItemClicked(@NonNull final RecyclerView recyclerView, @NonNull final CarouselLayoutManager carouselLayoutManager, @NonNull final View v);
|
||||
}
|
||||
@@ -63,6 +63,7 @@ public class CarouselLayoutManager extends RecyclerView.LayoutManager implements
|
||||
private PostLayoutListener mViewPostLayout;
|
||||
|
||||
private final List<OnCenterItemSelectionListener> mOnCenterItemSelectionListeners = new ArrayList<>();
|
||||
private final List<OnDargAutoDiffListener> onDargAutoDiffListeners = new ArrayList<>();
|
||||
private int mCenterItemPosition = INVALID_POSITION;
|
||||
private int mItemsCount;
|
||||
|
||||
@@ -188,6 +189,14 @@ public class CarouselLayoutManager extends RecyclerView.LayoutManager implements
|
||||
mOnCenterItemSelectionListeners.remove(onCenterItemSelectionListener);
|
||||
}
|
||||
|
||||
public void addOnDargAutoDiffListener(@NonNull final OnDargAutoDiffListener onDargAutoDiffListener) {
|
||||
onDargAutoDiffListeners.add(onDargAutoDiffListener);
|
||||
}
|
||||
|
||||
public void removeOnDargAutoDiffListener(@NonNull final OnDargAutoDiffListener onDargAutoDiffListener) {
|
||||
onDargAutoDiffListeners.remove(onDargAutoDiffListener);
|
||||
}
|
||||
|
||||
@SuppressWarnings("RefusedBequest")
|
||||
@Override
|
||||
public void scrollToPosition(final int position) {
|
||||
@@ -439,7 +448,9 @@ public class CarouselLayoutManager extends RecyclerView.LayoutManager implements
|
||||
private void detectOnItemSelectionChanged(final float currentScrollPosition, final RecyclerView.State state) {
|
||||
final float absCurrentScrollPosition = makeScrollPositionInRange0ToCount(currentScrollPosition, state.getItemCount());
|
||||
final int centerItem = Math.round(absCurrentScrollPosition);
|
||||
|
||||
if(currentScrollPosition-centerItem!=0){
|
||||
new Handler(Looper.getMainLooper()).post(() -> dragDxDiff(currentScrollPosition,mCenterItemPosition));
|
||||
}
|
||||
if (mCenterItemPosition != centerItem) {
|
||||
mCenterItemPosition = centerItem;
|
||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||
@@ -456,6 +467,11 @@ public class CarouselLayoutManager extends RecyclerView.LayoutManager implements
|
||||
onCenterItemSelectionListener.onCenterItemChanged(centerItem);
|
||||
}
|
||||
}
|
||||
private void dragDxDiff(final float centerItem,final int currentPosition) {
|
||||
for (final OnDargAutoDiffListener onDargAutoDiffListener : onDargAutoDiffListeners) {
|
||||
onDargAutoDiffListener.onDxChanged(centerItem,currentPosition);
|
||||
}
|
||||
}
|
||||
|
||||
private void fillDataVertical(final RecyclerView.Recycler recycler, final int width, final int height) {
|
||||
final int start = (width - mDecoratedChildWidth) / 2;
|
||||
@@ -781,6 +797,10 @@ public class CarouselLayoutManager extends RecyclerView.LayoutManager implements
|
||||
void onCenterItemChanged(final int adapterPosition);
|
||||
}
|
||||
|
||||
public interface OnDargAutoDiffListener {
|
||||
void onDxChanged(final float adapterPosition,final int currentPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class that holds currently visible items.
|
||||
* Generally this class fills this list. <br />
|
||||
|
||||
@@ -26,16 +26,6 @@ public class CarouselZoomPostLayoutListener extends CarouselLayoutManager.PostLa
|
||||
@Override
|
||||
public ItemTransformation transformChild(@NonNull final View child, final float itemPositionToCenterDiff, final int orientation) {
|
||||
float scale = 1.0f - mScaleMultiplier * Math.abs(itemPositionToCenterDiff);
|
||||
// float scale;
|
||||
// if(itemPositionToCenterDiff==1||itemPositionToCenterDiff==-1){
|
||||
// scale = 0.79f;
|
||||
// }else {
|
||||
// scale = 1.0f - mScaleMultiplier * Math.abs(itemPositionToCenterDiff);
|
||||
// if(scale<0.79){
|
||||
// scale = 0.79f;
|
||||
// }
|
||||
// }
|
||||
// because scaling will make view smaller in its center, then we should move this item to the top or bottom to make it visible
|
||||
final float translateY;
|
||||
final float translateX;
|
||||
if (CarouselLayoutManager.VERTICAL == orientation) {
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.mogo.och.taxi.passenger.ui.video.layoutmanage;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class DefaultChildSelectionListener extends CarouselChildSelectionListener {
|
||||
|
||||
@NonNull
|
||||
private final OnCenterItemClickListener mOnCenterItemClickListener;
|
||||
|
||||
protected DefaultChildSelectionListener(@NonNull final OnCenterItemClickListener onCenterItemClickListener, @NonNull final RecyclerView recyclerView, @NonNull final CarouselLayoutManager carouselLayoutManager) {
|
||||
super(recyclerView, carouselLayoutManager);
|
||||
|
||||
mOnCenterItemClickListener = onCenterItemClickListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCenterItemClicked(@NonNull final RecyclerView recyclerView, @NonNull final CarouselLayoutManager carouselLayoutManager, @NonNull final View v) {
|
||||
mOnCenterItemClickListener.onCenterItemClicked(recyclerView, carouselLayoutManager, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBackItemClicked(@NonNull final RecyclerView recyclerView, @NonNull final CarouselLayoutManager carouselLayoutManager, @NonNull final View v) {
|
||||
recyclerView.smoothScrollToPosition(carouselLayoutManager.getPosition(v));
|
||||
}
|
||||
|
||||
public static DefaultChildSelectionListener initCenterItemListener(@NonNull final OnCenterItemClickListener onCenterItemClickListener, @NonNull final RecyclerView recyclerView, @NonNull final CarouselLayoutManager carouselLayoutManager) {
|
||||
return new DefaultChildSelectionListener(onCenterItemClickListener, recyclerView, carouselLayoutManager);
|
||||
}
|
||||
|
||||
public interface OnCenterItemClickListener {
|
||||
|
||||
void onCenterItemClicked(@NonNull final RecyclerView recyclerView, @NonNull final CarouselLayoutManager carouselLayoutManager, @NonNull final View v);
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import com.mogo.eagle.core.utilcode.util.TimeTransformUtils
|
||||
import com.mogo.eagle.core.widget.media.video.TextureVideoViewOutlineProvider
|
||||
import com.mogo.och.taxi.passenger.R
|
||||
import com.mogo.och.taxi.passenger.ui.video.FullVideoUtils
|
||||
import com.shuyu.gsyvideoplayer.listener.VideoAllCallBack
|
||||
import com.shuyu.gsyvideoplayer.utils.Debuger
|
||||
import com.shuyu.gsyvideoplayer.utils.GSYVideoType
|
||||
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
|
||||
@@ -118,11 +119,12 @@ class ConsultVideoPlayer : StandardGSYVideoPlayer {
|
||||
fullVideoPlayer?.let {
|
||||
clearFullscreenLayout(it)
|
||||
}
|
||||
onVideoReset()
|
||||
fullVideoPlayer?.onVideoReset()
|
||||
if (thumbImageView is ImageView) {
|
||||
(thumbImageView as ImageView).setImageResource(R.drawable.taxi_p_video_holder)
|
||||
}
|
||||
|
||||
}else{
|
||||
onVideoReset()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,16 +284,16 @@ class ConsultVideoPlayer : StandardGSYVideoPlayer {
|
||||
width, height
|
||||
)
|
||||
frameLayout.addView(gsyVideoPlayer, lp)
|
||||
FullVideoUtils.showOverlayView(context as Activity,frameLayout)
|
||||
FullVideoUtils.showOverlayView(context as Activity,frameLayout,R.style.och_window_anim_alpha)
|
||||
gsyVideoPlayer.visibility = INVISIBLE
|
||||
frameLayout.visibility = INVISIBLE
|
||||
resolveFullVideoShow(context, gsyVideoPlayer, frameLayout)
|
||||
|
||||
gsyVideoPlayer.addTextureView()
|
||||
gsyVideoPlayer.startProgressTimer()
|
||||
gsyVideoManager.setLastListener(this)
|
||||
gsyVideoManager.setListener(gsyVideoPlayer)
|
||||
checkoutState()
|
||||
thumbImageViewLayout.visibility = View.VISIBLE
|
||||
return gsyVideoPlayer
|
||||
} catch (e: java.lang.Exception) {
|
||||
e.printStackTrace()
|
||||
@@ -365,5 +367,9 @@ class ConsultVideoPlayer : StandardGSYVideoPlayer {
|
||||
}
|
||||
this.fullVideoPlayer = null
|
||||
}
|
||||
|
||||
fun getVideoAllCallBack(): VideoAllCallBack? {
|
||||
return mVideoAllCallBack
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.mogo.och.taxi.passenger.widget.indicator
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.util.AttributeSet
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.annotation.AIndicatorOrientation
|
||||
|
||||
import com.zhpan.indicator.base.BaseIndicatorView
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.drawer.DrawerProxy
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorOrientation
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.option.AttrsController
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.option.IndicatorOptions
|
||||
|
||||
class IndicatorView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : BaseIndicatorView(context, attrs, defStyleAttr) {
|
||||
|
||||
private var mDrawerProxy: DrawerProxy
|
||||
|
||||
init {
|
||||
AttrsController.initAttrs(context, attrs, mIndicatorOptions)
|
||||
mDrawerProxy = DrawerProxy(mIndicatorOptions)
|
||||
}
|
||||
|
||||
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
||||
super.onLayout(changed, left, top, right, bottom)
|
||||
mDrawerProxy.onLayout(changed, left, top, right, bottom)
|
||||
}
|
||||
|
||||
override fun onMeasure(
|
||||
widthMeasureSpec: Int,
|
||||
heightMeasureSpec: Int
|
||||
) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||
val measureResult = mDrawerProxy.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||
setMeasuredDimension(measureResult.measureWidth, measureResult.measureHeight)
|
||||
}
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
super.onDraw(canvas)
|
||||
rotateCanvas(canvas)
|
||||
mDrawerProxy.onDraw(canvas)
|
||||
}
|
||||
|
||||
override fun setIndicatorOptions(options: IndicatorOptions) {
|
||||
super.setIndicatorOptions(options)
|
||||
mDrawerProxy.setIndicatorOptions(options)
|
||||
}
|
||||
|
||||
override fun notifyDataChanged(itemCount:Int) {
|
||||
mDrawerProxy = DrawerProxy(mIndicatorOptions)
|
||||
super.notifyDataChanged(itemCount)
|
||||
}
|
||||
|
||||
private fun rotateCanvas(canvas: Canvas) {
|
||||
if (mIndicatorOptions.orientation == IndicatorOrientation.INDICATOR_VERTICAL) {
|
||||
canvas.rotate(90f, width / 2f, width / 2f)
|
||||
} else if (mIndicatorOptions.orientation == IndicatorOrientation.INDICATOR_RTL) {
|
||||
canvas.rotate(180f, width / 2f, height / 2f)
|
||||
}
|
||||
}
|
||||
|
||||
fun setOrientation(@AIndicatorOrientation orientation: Int) {
|
||||
mIndicatorOptions.orientation = orientation;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.mogo.och.taxi.passenger.widget.indicator.annotation
|
||||
|
||||
import androidx.annotation.IntDef
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorOrientation
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangpan
|
||||
* @date 2021/1/21
|
||||
*/
|
||||
@IntDef(
|
||||
IndicatorOrientation.INDICATOR_HORIZONTAL, IndicatorOrientation.INDICATOR_VERTICAL,
|
||||
IndicatorOrientation.INDICATOR_RTL
|
||||
)
|
||||
@kotlin.annotation.Retention(AnnotationRetention.SOURCE)
|
||||
@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FIELD)
|
||||
annotation class AIndicatorOrientation()
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.mogo.och.taxi.passenger.widget.indicator.annotation
|
||||
|
||||
import androidx.annotation.IntDef
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorSlideMode.Companion.COLOR
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorSlideMode.Companion.NORMAL
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorSlideMode.Companion.SCALE
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorSlideMode.Companion.SMOOTH
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorSlideMode.Companion.WORM
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Created by zhangpan on 2019-10-18.
|
||||
* Description:
|
||||
</pre> *
|
||||
*/
|
||||
@IntDef(NORMAL, SMOOTH, WORM, COLOR, SCALE)
|
||||
@kotlin.annotation.Retention(AnnotationRetention.SOURCE)
|
||||
@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FIELD)
|
||||
annotation class AIndicatorSlideMode
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.mogo.och.taxi.passenger.widget.indicator.annotation
|
||||
|
||||
import androidx.annotation.IntDef
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorStyle
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Created by zhangpan on 2019-10-18.
|
||||
* Description:
|
||||
</pre> *
|
||||
*/
|
||||
@IntDef(IndicatorStyle.CIRCLE, IndicatorStyle.DASH, IndicatorStyle.ROUND_RECT)
|
||||
@kotlin.annotation.Retention(AnnotationRetention.SOURCE)
|
||||
@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FIELD)
|
||||
annotation class AIndicatorStyle
|
||||
@@ -0,0 +1,207 @@
|
||||
package com.zhpan.indicator.base
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.annotation.AIndicatorSlideMode
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.annotation.AIndicatorStyle
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.base.IIndicator
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorSlideMode
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.option.IndicatorOptions
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Created by zhangpan on 2019-09-04.
|
||||
* Description:IndicatorView基类,处理了页面滑动。
|
||||
* </pre>
|
||||
*/
|
||||
@Suppress("UNUSED")
|
||||
open class BaseIndicatorView constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet?,
|
||||
defStyleAttr: Int
|
||||
) : View(context, attrs, defStyleAttr), IIndicator {
|
||||
|
||||
var mIndicatorOptions: IndicatorOptions
|
||||
|
||||
private var recyclerView: RecyclerView? = null
|
||||
|
||||
init {
|
||||
mIndicatorOptions = IndicatorOptions()
|
||||
}
|
||||
|
||||
fun setPageSize(pageSize: Int): BaseIndicatorView {
|
||||
mIndicatorOptions.pageSize = pageSize
|
||||
return this
|
||||
}
|
||||
|
||||
// 页面选定
|
||||
fun onPageSelected(position: Int) {
|
||||
System.err.println("BaseIndicatorView---onPageSelected:" + position)
|
||||
if (getSlideMode() == IndicatorSlideMode.NORMAL) {
|
||||
setCurrentPosition(position)
|
||||
setSlideProgress(0f)
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
// 滚动距离
|
||||
fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
if (getSlideMode() != IndicatorSlideMode.NORMAL && getPageSize() > 1) {
|
||||
scrollSlider(position, positionOffset)
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
private fun scrollSlider(position: Int, positionOffset: Float) {
|
||||
if (mIndicatorOptions.slideMode == IndicatorSlideMode.SCALE
|
||||
|| mIndicatorOptions.slideMode == IndicatorSlideMode.COLOR) {
|
||||
setCurrentPosition(position)
|
||||
setSlideProgress(positionOffset)
|
||||
} else {
|
||||
if (position % getPageSize() == getPageSize() - 1) { // 最后一个页面与第一个页面
|
||||
if (positionOffset < 0.5) {
|
||||
setCurrentPosition(position)
|
||||
setSlideProgress(0f)
|
||||
} else {
|
||||
setCurrentPosition(0)
|
||||
setSlideProgress(0f)
|
||||
}
|
||||
} else { // 中间页面
|
||||
setCurrentPosition(position)
|
||||
setSlideProgress(positionOffset)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun notifyDataChanged(itemCount: Int) {
|
||||
setPageSize(itemCount)
|
||||
requestLayout()
|
||||
invalidate()
|
||||
}
|
||||
|
||||
private fun setupViewPager() {
|
||||
|
||||
}
|
||||
|
||||
fun getNormalSlideWidth(): Float {
|
||||
return mIndicatorOptions.normalSliderWidth
|
||||
}
|
||||
|
||||
fun setNormalSlideWidth(normalSliderWidth: Float) {
|
||||
mIndicatorOptions.normalSliderWidth = normalSliderWidth
|
||||
}
|
||||
|
||||
fun getCheckedSlideWidth(): Float {
|
||||
return mIndicatorOptions.checkedSliderWidth
|
||||
}
|
||||
|
||||
fun setCheckedSlideWidth(checkedSliderWidth: Float) {
|
||||
mIndicatorOptions.checkedSliderWidth = checkedSliderWidth
|
||||
}
|
||||
|
||||
val checkedSliderWidth: Float
|
||||
get() = mIndicatorOptions.checkedSliderWidth
|
||||
|
||||
fun setCurrentPosition(currentPosition: Int) {
|
||||
mIndicatorOptions.currentPosition = currentPosition
|
||||
}
|
||||
|
||||
fun getCurrentPosition(): Int {
|
||||
return mIndicatorOptions.currentPosition
|
||||
}
|
||||
|
||||
fun getIndicatorGap(indicatorGap: Float) {
|
||||
mIndicatorOptions.sliderGap = indicatorGap
|
||||
}
|
||||
|
||||
fun setIndicatorGap(indicatorGap: Float) {
|
||||
mIndicatorOptions.sliderGap = indicatorGap
|
||||
}
|
||||
|
||||
fun setCheckedColor(@ColorInt normalColor: Int) {
|
||||
mIndicatorOptions.checkedSliderColor = normalColor
|
||||
}
|
||||
|
||||
fun getCheckedColor(): Int {
|
||||
return mIndicatorOptions.checkedSliderColor
|
||||
}
|
||||
|
||||
fun setNormalColor(@ColorInt normalColor: Int) {
|
||||
mIndicatorOptions.normalSliderColor = normalColor
|
||||
}
|
||||
|
||||
fun getSlideProgress(): Float {
|
||||
return mIndicatorOptions.slideProgress
|
||||
}
|
||||
|
||||
fun setSlideProgress(slideProgress: Float) {
|
||||
mIndicatorOptions.slideProgress = slideProgress
|
||||
}
|
||||
|
||||
fun getPageSize(): Int {
|
||||
return mIndicatorOptions.pageSize
|
||||
}
|
||||
|
||||
fun setSliderColor(
|
||||
@ColorInt normalColor: Int,
|
||||
@ColorInt selectedColor: Int
|
||||
): BaseIndicatorView {
|
||||
mIndicatorOptions.setSliderColor(normalColor, selectedColor)
|
||||
return this
|
||||
}
|
||||
|
||||
fun setSliderWidth(sliderWidth: Float): BaseIndicatorView {
|
||||
mIndicatorOptions.setSliderWidth(sliderWidth)
|
||||
return this
|
||||
}
|
||||
|
||||
fun setSliderWidth(
|
||||
normalSliderWidth: Float,
|
||||
selectedSliderWidth: Float
|
||||
): BaseIndicatorView {
|
||||
mIndicatorOptions.setSliderWidth(normalSliderWidth, selectedSliderWidth)
|
||||
return this
|
||||
}
|
||||
|
||||
fun setSliderGap(sliderGap: Float): BaseIndicatorView {
|
||||
mIndicatorOptions.sliderGap = sliderGap
|
||||
return this
|
||||
}
|
||||
|
||||
fun getSlideMode(): Int {
|
||||
return mIndicatorOptions.slideMode
|
||||
}
|
||||
|
||||
fun setSlideMode(@AIndicatorSlideMode slideMode: Int): BaseIndicatorView {
|
||||
mIndicatorOptions.slideMode = slideMode
|
||||
return this
|
||||
}
|
||||
|
||||
fun setIndicatorStyle(@AIndicatorStyle indicatorStyle: Int): BaseIndicatorView {
|
||||
mIndicatorOptions.indicatorStyle = indicatorStyle
|
||||
return this
|
||||
}
|
||||
|
||||
fun setSliderHeight(sliderHeight: Float): BaseIndicatorView {
|
||||
mIndicatorOptions.sliderHeight = sliderHeight
|
||||
return this
|
||||
}
|
||||
|
||||
fun showIndicatorWhenOneItem(showIndicatorWhenOneItem: Boolean) {
|
||||
mIndicatorOptions.showIndicatorOneItem = showIndicatorWhenOneItem
|
||||
}
|
||||
|
||||
fun onPageScrollStateChanged(state: Int) {
|
||||
}
|
||||
|
||||
override fun setIndicatorOptions(options: IndicatorOptions) {
|
||||
mIndicatorOptions = options
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.mogo.och.taxi.passenger.widget.indicator.base
|
||||
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.option.IndicatorOptions
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Created by zhangpan on 2019-09-02.
|
||||
* Description:
|
||||
</pre> *
|
||||
*/
|
||||
interface IIndicator {
|
||||
|
||||
fun notifyDataChanged(itemCount:Int)
|
||||
|
||||
fun setIndicatorOptions(options: IndicatorOptions)
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.mogo.och.taxi.passenger.widget.indicator.drawer
|
||||
|
||||
import android.animation.ArgbEvaluator
|
||||
import android.graphics.Paint
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorOrientation
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorSlideMode
|
||||
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.option.IndicatorOptions
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Created by zhpan on 2019/11/23.
|
||||
* Description:
|
||||
</pre> *
|
||||
*/
|
||||
abstract class BaseDrawer internal constructor(internal var mIndicatorOptions: IndicatorOptions) :
|
||||
IDrawer {
|
||||
|
||||
private val mMeasureResult: MeasureResult
|
||||
internal var maxWidth: Float = 0.toFloat()
|
||||
internal var minWidth: Float = 0.toFloat()
|
||||
internal var mPaint: Paint = Paint()
|
||||
internal var argbEvaluator: ArgbEvaluator? = null
|
||||
|
||||
companion object {
|
||||
const val INDICATOR_PADDING_ADDITION = 6
|
||||
const val INDICATOR_PADDING = 3
|
||||
}
|
||||
|
||||
protected val isWidthEquals: Boolean
|
||||
get() = mIndicatorOptions.normalSliderWidth == mIndicatorOptions.checkedSliderWidth
|
||||
|
||||
init {
|
||||
mPaint.isAntiAlias = true
|
||||
mMeasureResult = MeasureResult()
|
||||
if (mIndicatorOptions.slideMode == IndicatorSlideMode.SCALE
|
||||
|| mIndicatorOptions.slideMode == IndicatorSlideMode.COLOR
|
||||
) {
|
||||
argbEvaluator = ArgbEvaluator()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMeasure(
|
||||
widthMeasureSpec: Int,
|
||||
heightMeasureSpec: Int
|
||||
): MeasureResult {
|
||||
maxWidth =
|
||||
mIndicatorOptions.normalSliderWidth.coerceAtLeast(mIndicatorOptions.checkedSliderWidth)
|
||||
minWidth =
|
||||
mIndicatorOptions.normalSliderWidth.coerceAtMost(mIndicatorOptions.checkedSliderWidth)
|
||||
if (mIndicatorOptions.orientation == IndicatorOrientation.INDICATOR_VERTICAL) {
|
||||
mMeasureResult.setMeasureResult(measureHeight(), measureWidth())
|
||||
} else {
|
||||
mMeasureResult.setMeasureResult(measureWidth(), measureHeight())
|
||||
}
|
||||
return mMeasureResult
|
||||
}
|
||||
|
||||
protected open fun measureHeight(): Int {
|
||||
return mIndicatorOptions.sliderHeight.toInt() + INDICATOR_PADDING
|
||||
}
|
||||
|
||||
private fun measureWidth(): Int {
|
||||
val pageSize = mIndicatorOptions.pageSize
|
||||
val indicatorGap = mIndicatorOptions.sliderGap
|
||||
return ((pageSize - 1) * indicatorGap + maxWidth + (pageSize - 1) * minWidth).toInt() + INDICATOR_PADDING_ADDITION
|
||||
}
|
||||
|
||||
override fun onLayout(
|
||||
changed: Boolean,
|
||||
left: Int,
|
||||
top: Int,
|
||||
right: Int,
|
||||
bottom: Int
|
||||
) {
|
||||
}
|
||||
|
||||
inner class MeasureResult {
|
||||
|
||||
var measureWidth: Int = 0
|
||||
internal set
|
||||
|
||||
var measureHeight: Int = 0
|
||||
internal set
|
||||
|
||||
internal fun setMeasureResult(
|
||||
measureWidth: Int,
|
||||
measureHeight: Int
|
||||
) {
|
||||
this.measureWidth = measureWidth
|
||||
this.measureHeight = measureHeight
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package com.mogo.och.taxi.passenger.widget.indicator.drawer
|
||||
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.RectF
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorSlideMode
|
||||
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.option.IndicatorOptions
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.utils.IndicatorUtils
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Created by zhpan on 2019/11/23.
|
||||
* Description: Circle Indicator drawer.
|
||||
</pre> *
|
||||
*/
|
||||
class CircleDrawer internal constructor(indicatorOptions: IndicatorOptions) : BaseDrawer(
|
||||
indicatorOptions
|
||||
) {
|
||||
|
||||
private val rectF = RectF()
|
||||
|
||||
override fun measureHeight(): Int {
|
||||
return maxWidth.toInt() + INDICATOR_PADDING_ADDITION
|
||||
}
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
val pageSize = mIndicatorOptions.pageSize
|
||||
if (pageSize > 1 || mIndicatorOptions.showIndicatorOneItem && pageSize == 1) {
|
||||
drawNormal(canvas)
|
||||
drawSlider(canvas)
|
||||
}
|
||||
}
|
||||
|
||||
private fun drawNormal(canvas: Canvas) {
|
||||
val normalIndicatorWidth = mIndicatorOptions.normalSliderWidth
|
||||
mPaint.color = mIndicatorOptions.normalSliderColor
|
||||
for (i in 0 until mIndicatorOptions.pageSize) {
|
||||
val coordinateX = IndicatorUtils.getCoordinateX(mIndicatorOptions, maxWidth, i)
|
||||
val coordinateY = IndicatorUtils.getCoordinateY(maxWidth)
|
||||
drawCircle(canvas, coordinateX, coordinateY, normalIndicatorWidth / 2)
|
||||
}
|
||||
}
|
||||
|
||||
private fun drawSlider(canvas: Canvas) {
|
||||
mPaint.color = mIndicatorOptions.checkedSliderColor
|
||||
when (mIndicatorOptions.slideMode) {
|
||||
IndicatorSlideMode.NORMAL, IndicatorSlideMode.SMOOTH -> drawCircleSlider(canvas)
|
||||
IndicatorSlideMode.WORM -> drawWormSlider(canvas)
|
||||
IndicatorSlideMode.SCALE -> drawScaleSlider(canvas)
|
||||
IndicatorSlideMode.COLOR -> drawColor(canvas)
|
||||
}
|
||||
}
|
||||
|
||||
private fun drawColor(canvas: Canvas) {
|
||||
val currentPosition = mIndicatorOptions.currentPosition
|
||||
val slideProgress = mIndicatorOptions.slideProgress
|
||||
val coordinateX = IndicatorUtils.getCoordinateX(mIndicatorOptions, maxWidth, currentPosition)
|
||||
val coordinateY = IndicatorUtils.getCoordinateY(maxWidth)
|
||||
var evaluate = argbEvaluator?.evaluate(
|
||||
slideProgress, mIndicatorOptions.checkedSliderColor, mIndicatorOptions.normalSliderColor
|
||||
)
|
||||
mPaint.color = (evaluate as Int)
|
||||
drawCircle(canvas, coordinateX, coordinateY, mIndicatorOptions.normalSliderWidth / 2)
|
||||
|
||||
// 绘制可循环的ViewPager指示器渐变
|
||||
evaluate = argbEvaluator?.evaluate(
|
||||
1 - slideProgress, mIndicatorOptions.checkedSliderColor, mIndicatorOptions.normalSliderColor
|
||||
)
|
||||
mPaint.color = evaluate as Int
|
||||
val nextCoordinateX = if (currentPosition == mIndicatorOptions.pageSize - 1) {
|
||||
IndicatorUtils.getCoordinateX(mIndicatorOptions, maxWidth, 0)
|
||||
} else {
|
||||
coordinateX + mIndicatorOptions.sliderGap + mIndicatorOptions.normalSliderWidth
|
||||
}
|
||||
drawCircle(canvas, nextCoordinateX, coordinateY, mIndicatorOptions.checkedSliderWidth / 2)
|
||||
}
|
||||
|
||||
private fun drawScaleSlider(canvas: Canvas) {
|
||||
val currentPosition = mIndicatorOptions.currentPosition
|
||||
val slideProgress = mIndicatorOptions.slideProgress
|
||||
val coordinateX = IndicatorUtils.getCoordinateX(mIndicatorOptions, maxWidth, currentPosition)
|
||||
val coordinateY = IndicatorUtils.getCoordinateY(maxWidth)
|
||||
if (slideProgress < 1) {
|
||||
val evaluate = argbEvaluator?.evaluate(
|
||||
slideProgress, mIndicatorOptions.checkedSliderColor, mIndicatorOptions.normalSliderColor
|
||||
)
|
||||
mPaint.color = (evaluate as Int)
|
||||
val radius =
|
||||
mIndicatorOptions.checkedSliderWidth / 2 - (mIndicatorOptions.checkedSliderWidth / 2 - mIndicatorOptions.normalSliderWidth / 2) * slideProgress
|
||||
drawCircle(canvas, coordinateX, coordinateY, radius)
|
||||
}
|
||||
|
||||
if (currentPosition == mIndicatorOptions.pageSize - 1) {
|
||||
val evaluate = argbEvaluator?.evaluate(
|
||||
slideProgress, mIndicatorOptions.normalSliderColor, mIndicatorOptions.checkedSliderColor
|
||||
)
|
||||
mPaint.color = evaluate as Int
|
||||
val nextCoordinateX = maxWidth / 2
|
||||
val nextRadius = minWidth / 2 + (maxWidth / 2 - minWidth / 2) * (slideProgress)
|
||||
drawCircle(canvas, nextCoordinateX, coordinateY, nextRadius)
|
||||
} else {
|
||||
if (slideProgress > 0) {
|
||||
val evaluate = argbEvaluator?.evaluate(
|
||||
slideProgress, mIndicatorOptions.normalSliderColor, mIndicatorOptions.checkedSliderColor
|
||||
)
|
||||
mPaint.color = evaluate as Int
|
||||
val nextCoordinateX =
|
||||
coordinateX + mIndicatorOptions.sliderGap + mIndicatorOptions.normalSliderWidth
|
||||
val nextRadius =
|
||||
mIndicatorOptions.normalSliderWidth / 2 + (mIndicatorOptions.checkedSliderWidth / 2 - mIndicatorOptions.normalSliderWidth / 2) * slideProgress
|
||||
drawCircle(canvas, nextCoordinateX, coordinateY, nextRadius)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun drawCircleSlider(canvas: Canvas) {
|
||||
val currentPosition = mIndicatorOptions.currentPosition
|
||||
val startCoordinateX =
|
||||
IndicatorUtils.getCoordinateX(mIndicatorOptions, maxWidth, currentPosition)
|
||||
val endCoordinateX = IndicatorUtils.getCoordinateX(
|
||||
mIndicatorOptions, maxWidth, (currentPosition + 1) % mIndicatorOptions.pageSize
|
||||
)
|
||||
val coordinateX =
|
||||
startCoordinateX + (endCoordinateX - startCoordinateX) * mIndicatorOptions.slideProgress
|
||||
val coordinateY = IndicatorUtils.getCoordinateY(maxWidth)
|
||||
val radius = mIndicatorOptions.checkedSliderWidth / 2
|
||||
drawCircle(canvas, coordinateX, coordinateY, radius)
|
||||
}
|
||||
|
||||
private fun drawWormSlider(canvas: Canvas) {
|
||||
val sliderHeight = mIndicatorOptions.normalSliderWidth
|
||||
val slideProgress = mIndicatorOptions.slideProgress
|
||||
val currentPosition = mIndicatorOptions.currentPosition
|
||||
val distance = mIndicatorOptions.sliderGap + mIndicatorOptions.normalSliderWidth
|
||||
val startCoordinateX =
|
||||
IndicatorUtils.getCoordinateX(mIndicatorOptions, maxWidth, currentPosition)
|
||||
val left = startCoordinateX + (distance * (slideProgress - 0.5f) * 2.0f).coerceAtLeast(
|
||||
0f
|
||||
) - mIndicatorOptions.normalSliderWidth / 2 + INDICATOR_PADDING
|
||||
val right = startCoordinateX + (distance * slideProgress * 2f).coerceAtMost(
|
||||
distance
|
||||
) + mIndicatorOptions.normalSliderWidth / 2 + INDICATOR_PADDING
|
||||
rectF.set(left, INDICATOR_PADDING.toFloat(), right, sliderHeight + INDICATOR_PADDING)
|
||||
canvas.drawRoundRect(rectF, sliderHeight, sliderHeight, mPaint)
|
||||
}
|
||||
|
||||
private fun drawCircle(
|
||||
canvas: Canvas,
|
||||
coordinateX: Float,
|
||||
coordinateY: Float,
|
||||
radius: Float
|
||||
) {
|
||||
canvas.drawCircle(
|
||||
coordinateX + INDICATOR_PADDING, coordinateY + INDICATOR_PADDING, radius, mPaint
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.mogo.och.taxi.passenger.widget.indicator.drawer
|
||||
|
||||
import android.graphics.Canvas
|
||||
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.option.IndicatorOptions
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Created by zhpan on 2019/11/23.
|
||||
* Description: Dash Indicator Drawer.
|
||||
</pre> *
|
||||
*/
|
||||
class DashDrawer internal constructor(indicatorOptions: IndicatorOptions) : RectDrawer(
|
||||
indicatorOptions
|
||||
) {
|
||||
|
||||
override fun drawDash(canvas: Canvas) {
|
||||
canvas.drawRect(mRectF, mPaint)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.mogo.och.taxi.passenger.widget.indicator.drawer
|
||||
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorStyle
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.option.IndicatorOptions
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Created by zhpan on 2019/11/24.
|
||||
* Description: Indicator Drawer Factory.
|
||||
</pre> *
|
||||
*/
|
||||
internal object DrawerFactory {
|
||||
fun createDrawer(indicatorOptions: IndicatorOptions): IDrawer {
|
||||
return when (indicatorOptions.indicatorStyle) {
|
||||
IndicatorStyle.DASH -> DashDrawer(indicatorOptions)
|
||||
IndicatorStyle.ROUND_RECT -> RoundRectDrawer(indicatorOptions)
|
||||
else -> CircleDrawer(indicatorOptions)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.mogo.och.taxi.passenger.widget.indicator.drawer
|
||||
|
||||
import android.graphics.Canvas
|
||||
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.option.IndicatorOptions
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Created by zhpan on 2019/11/23.
|
||||
* Description: Indicator Drawer Proxy.
|
||||
</pre> *
|
||||
*/
|
||||
class DrawerProxy(indicatorOptions: IndicatorOptions) : IDrawer {
|
||||
|
||||
private lateinit var mIDrawer: IDrawer
|
||||
|
||||
init {
|
||||
init(indicatorOptions)
|
||||
}
|
||||
|
||||
private fun init(indicatorOptions: IndicatorOptions) {
|
||||
mIDrawer = DrawerFactory.createDrawer(indicatorOptions)
|
||||
}
|
||||
|
||||
override fun onLayout(
|
||||
changed: Boolean,
|
||||
left: Int,
|
||||
top: Int,
|
||||
right: Int,
|
||||
bottom: Int
|
||||
) {
|
||||
}
|
||||
|
||||
override fun onMeasure(
|
||||
widthMeasureSpec: Int,
|
||||
heightMeasureSpec: Int
|
||||
): BaseDrawer.MeasureResult {
|
||||
return mIDrawer.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||
}
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
mIDrawer.onDraw(canvas)
|
||||
}
|
||||
|
||||
fun setIndicatorOptions(indicatorOptions: IndicatorOptions) {
|
||||
init(indicatorOptions)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.mogo.och.taxi.passenger.widget.indicator.drawer
|
||||
|
||||
import android.graphics.Canvas
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.drawer.BaseDrawer
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Created by zhpan on 2019/11/23.
|
||||
* Description:
|
||||
</pre> *
|
||||
*/
|
||||
interface IDrawer {
|
||||
|
||||
fun onLayout(
|
||||
changed: Boolean,
|
||||
left: Int,
|
||||
top: Int,
|
||||
right: Int,
|
||||
bottom: Int
|
||||
)
|
||||
|
||||
fun onMeasure(
|
||||
widthMeasureSpec: Int,
|
||||
heightMeasureSpec: Int
|
||||
): BaseDrawer.MeasureResult
|
||||
|
||||
fun onDraw(canvas: Canvas)
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
package com.mogo.och.taxi.passenger.widget.indicator.drawer
|
||||
|
||||
import android.graphics.*
|
||||
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorSlideMode
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.option.IndicatorOptions
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.utils.IndicatorUtils
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Created by zhpan on 2020/1/17.
|
||||
* Description:
|
||||
</pre> *
|
||||
*/
|
||||
open class RectDrawer internal constructor(indicatorOptions: IndicatorOptions) : BaseDrawer(
|
||||
indicatorOptions
|
||||
) {
|
||||
internal var mRectF: RectF = RectF()
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
val pageSize = mIndicatorOptions.pageSize
|
||||
if (pageSize > 1 || mIndicatorOptions.showIndicatorOneItem && pageSize == 1) {
|
||||
if (isWidthEquals && mIndicatorOptions.slideMode != IndicatorSlideMode.NORMAL) {
|
||||
drawUncheckedSlider(canvas, pageSize)
|
||||
drawCheckedSlider(canvas)
|
||||
} else { // 单独处理normalWidth与checkedWidth不一致的情况
|
||||
if (mIndicatorOptions.slideMode == IndicatorSlideMode.SCALE) {
|
||||
for (i in 0 until pageSize) {
|
||||
drawScaleSlider(canvas, i)
|
||||
}
|
||||
} else {
|
||||
drawInequalitySlider(canvas, pageSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun drawScaleSlider(
|
||||
canvas: Canvas,
|
||||
i: Int
|
||||
) {
|
||||
val checkedColor = mIndicatorOptions.checkedSliderColor
|
||||
val indicatorGap = mIndicatorOptions.sliderGap
|
||||
val sliderHeight = mIndicatorOptions.sliderHeight
|
||||
val currentPosition = mIndicatorOptions.currentPosition
|
||||
val normalWidth = mIndicatorOptions.normalSliderWidth
|
||||
val checkedWidth = mIndicatorOptions.checkedSliderWidth
|
||||
when {
|
||||
i < currentPosition -> {
|
||||
mPaint.color = mIndicatorOptions.normalSliderColor
|
||||
val left: Float = if (currentPosition == mIndicatorOptions.pageSize - 1) {
|
||||
(i * normalWidth + i * indicatorGap) + (checkedWidth - normalWidth) * mIndicatorOptions.slideProgress
|
||||
} else {
|
||||
(i * normalWidth + i * indicatorGap)
|
||||
}
|
||||
mRectF.set(left, 0f, left + normalWidth, sliderHeight)
|
||||
drawRoundRect(canvas, sliderHeight, sliderHeight)
|
||||
}
|
||||
i == currentPosition -> {
|
||||
mPaint.color = checkedColor
|
||||
val slideProgress = mIndicatorOptions.slideProgress
|
||||
if (currentPosition == mIndicatorOptions.pageSize - 1) {
|
||||
val evaluate = argbEvaluator?.evaluate(
|
||||
slideProgress, checkedColor, mIndicatorOptions.normalSliderColor
|
||||
)
|
||||
mPaint.color = (evaluate as Int)
|
||||
val right =
|
||||
(mIndicatorOptions.pageSize - 1) * (normalWidth + mIndicatorOptions.sliderGap) + checkedWidth
|
||||
val left = right - checkedWidth + (checkedWidth - normalWidth) * (slideProgress)
|
||||
mRectF.set(left, 0f, right, sliderHeight)
|
||||
drawRoundRect(canvas, sliderHeight, sliderHeight)
|
||||
} else {
|
||||
if (slideProgress < 1) {
|
||||
val evaluate = argbEvaluator?.evaluate(
|
||||
slideProgress, checkedColor, mIndicatorOptions.normalSliderColor
|
||||
)
|
||||
mPaint.color = (evaluate as Int)
|
||||
val left = i * normalWidth + i * indicatorGap
|
||||
val right = left + normalWidth + (checkedWidth - normalWidth) * (1 - slideProgress)
|
||||
mRectF.set(left, 0f, right, sliderHeight)
|
||||
drawRoundRect(canvas, sliderHeight, sliderHeight)
|
||||
}
|
||||
}
|
||||
|
||||
if (currentPosition == mIndicatorOptions.pageSize - 1) {
|
||||
if (slideProgress > 0) {
|
||||
val evaluate = argbEvaluator?.evaluate(
|
||||
1 - slideProgress, checkedColor, mIndicatorOptions.normalSliderColor
|
||||
)
|
||||
mPaint.color = evaluate as Int
|
||||
val left = 0f
|
||||
val right = left + normalWidth + (checkedWidth - normalWidth) * slideProgress
|
||||
|
||||
mRectF.set(left, 0f, right, sliderHeight)
|
||||
drawRoundRect(canvas, sliderHeight, sliderHeight)
|
||||
}
|
||||
} else {
|
||||
if (slideProgress > 0) {
|
||||
val evaluate = argbEvaluator?.evaluate(
|
||||
1 - slideProgress, checkedColor, mIndicatorOptions.normalSliderColor
|
||||
)
|
||||
mPaint.color = evaluate as Int
|
||||
val right =
|
||||
i * normalWidth + i * indicatorGap + normalWidth + (indicatorGap + checkedWidth)
|
||||
val left = right - (normalWidth) - (checkedWidth - normalWidth) * (slideProgress)
|
||||
mRectF.set(left, 0f, right, sliderHeight)
|
||||
drawRoundRect(canvas, sliderHeight, sliderHeight)
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
if ((currentPosition + 1 != i || mIndicatorOptions.slideProgress == 0f)) { // 避免多余绘制
|
||||
mPaint.color = mIndicatorOptions.normalSliderColor
|
||||
val left = i * minWidth + i * indicatorGap + (checkedWidth - minWidth)
|
||||
mRectF.set(left, 0f, left + minWidth, sliderHeight)
|
||||
drawRoundRect(canvas, sliderHeight, sliderHeight)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun drawUncheckedSlider(
|
||||
canvas: Canvas,
|
||||
pageSize: Int
|
||||
) {
|
||||
for (i in 0 until pageSize) {
|
||||
mPaint.color = mIndicatorOptions.normalSliderColor
|
||||
val left = i * maxWidth + i * +mIndicatorOptions.sliderGap + (maxWidth - minWidth)
|
||||
mRectF.set(left, 0f, left + minWidth, mIndicatorOptions.sliderHeight)
|
||||
drawRoundRect(canvas, mIndicatorOptions.sliderHeight, mIndicatorOptions.sliderHeight)
|
||||
}
|
||||
}
|
||||
|
||||
private fun drawInequalitySlider(
|
||||
canvas: Canvas,
|
||||
pageSize: Int
|
||||
) {
|
||||
var left = 0f
|
||||
for (i in 0 until pageSize) {
|
||||
val sliderWidth = (if (i == mIndicatorOptions.currentPosition) maxWidth else minWidth)
|
||||
mPaint.color =
|
||||
if (i == mIndicatorOptions.currentPosition) mIndicatorOptions.checkedSliderColor else mIndicatorOptions.normalSliderColor
|
||||
mRectF.set(left, 0f, left + sliderWidth, mIndicatorOptions.sliderHeight)
|
||||
drawRoundRect(canvas, mIndicatorOptions.sliderHeight, mIndicatorOptions.sliderHeight)
|
||||
left += sliderWidth + mIndicatorOptions.sliderGap
|
||||
}
|
||||
}
|
||||
|
||||
private fun drawCheckedSlider(canvas: Canvas) {
|
||||
mPaint.color = mIndicatorOptions.checkedSliderColor
|
||||
when (mIndicatorOptions.slideMode) {
|
||||
IndicatorSlideMode.SMOOTH -> drawSmoothSlider(canvas)
|
||||
IndicatorSlideMode.WORM -> drawWormSlider(canvas)
|
||||
IndicatorSlideMode.COLOR -> drawColorSlider(canvas)
|
||||
}
|
||||
}
|
||||
|
||||
private fun drawColorSlider(canvas: Canvas) {
|
||||
val currentPosition = mIndicatorOptions.currentPosition
|
||||
val slideProgress = mIndicatorOptions.slideProgress
|
||||
val left = currentPosition * minWidth + currentPosition * mIndicatorOptions.sliderGap
|
||||
if (slideProgress < 0.99) {
|
||||
val evaluate = argbEvaluator?.evaluate(
|
||||
slideProgress, mIndicatorOptions.checkedSliderColor, mIndicatorOptions.normalSliderColor
|
||||
)
|
||||
mPaint.color = (evaluate as Int)
|
||||
mRectF.set(left, 0f, left + minWidth, mIndicatorOptions.sliderHeight)
|
||||
drawRoundRect(canvas, mIndicatorOptions.sliderHeight, mIndicatorOptions.sliderHeight)
|
||||
}
|
||||
|
||||
var nextSliderLeft = left + mIndicatorOptions.sliderGap + mIndicatorOptions.normalSliderWidth
|
||||
if (currentPosition == mIndicatorOptions.pageSize - 1) {
|
||||
nextSliderLeft = 0f
|
||||
}
|
||||
val evaluate = argbEvaluator?.evaluate(
|
||||
1 - slideProgress, mIndicatorOptions.checkedSliderColor, mIndicatorOptions.normalSliderColor
|
||||
)
|
||||
mPaint.color = evaluate as Int
|
||||
mRectF.set(nextSliderLeft, 0f, nextSliderLeft + minWidth, mIndicatorOptions.sliderHeight)
|
||||
drawRoundRect(canvas, mIndicatorOptions.sliderHeight, mIndicatorOptions.sliderHeight)
|
||||
}
|
||||
|
||||
private fun drawWormSlider(canvas: Canvas) {
|
||||
val sliderHeight = mIndicatorOptions.sliderHeight
|
||||
val slideProgress = mIndicatorOptions.slideProgress
|
||||
val currentPosition = mIndicatorOptions.currentPosition
|
||||
val distance = mIndicatorOptions.sliderGap + mIndicatorOptions.normalSliderWidth
|
||||
val startCoordinateX =
|
||||
IndicatorUtils.getCoordinateX(mIndicatorOptions, maxWidth, currentPosition)
|
||||
val left = startCoordinateX + (distance * (slideProgress - 0.5f) * 2.0f).coerceAtLeast(
|
||||
0f
|
||||
) - mIndicatorOptions.normalSliderWidth / 2
|
||||
val right = startCoordinateX + (distance * slideProgress * 2f).coerceAtMost(
|
||||
distance
|
||||
) + mIndicatorOptions.normalSliderWidth / 2
|
||||
mRectF.set(left, 0f, right, sliderHeight)
|
||||
drawRoundRect(canvas, sliderHeight, sliderHeight)
|
||||
}
|
||||
|
||||
private fun drawSmoothSlider(canvas: Canvas) {
|
||||
val currentPosition = mIndicatorOptions.currentPosition
|
||||
val indicatorGap = mIndicatorOptions.sliderGap
|
||||
val sliderHeight = mIndicatorOptions.sliderHeight
|
||||
val left =
|
||||
currentPosition * maxWidth + currentPosition * +indicatorGap + (maxWidth + indicatorGap) * mIndicatorOptions.slideProgress
|
||||
mRectF.set(left, 0f, left + maxWidth, sliderHeight)
|
||||
drawRoundRect(canvas, sliderHeight, sliderHeight)
|
||||
}
|
||||
|
||||
protected open fun drawRoundRect(
|
||||
canvas: Canvas,
|
||||
rx: Float,
|
||||
ry: Float
|
||||
) {
|
||||
drawDash(canvas)
|
||||
}
|
||||
|
||||
protected open fun drawDash(canvas: Canvas) {}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.mogo.och.taxi.passenger.widget.indicator.drawer
|
||||
|
||||
import android.graphics.Canvas
|
||||
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.option.IndicatorOptions
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Created by zhpan on 2019/11/26.
|
||||
* Description:
|
||||
</pre> *
|
||||
*/
|
||||
class RoundRectDrawer internal constructor(indicatorOptions: IndicatorOptions) : RectDrawer(
|
||||
indicatorOptions
|
||||
) {
|
||||
|
||||
override fun drawRoundRect(
|
||||
canvas: Canvas,
|
||||
rx: Float,
|
||||
ry: Float
|
||||
) {
|
||||
canvas.drawRoundRect(mRectF, rx, ry, mPaint)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.mogo.och.taxi.passenger.widget.indicator.enums
|
||||
|
||||
import android.widget.LinearLayout
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangpan
|
||||
* @date 2021/1/21
|
||||
*/
|
||||
class IndicatorOrientation {
|
||||
companion object {
|
||||
const val INDICATOR_HORIZONTAL = LinearLayout.HORIZONTAL
|
||||
const val INDICATOR_VERTICAL = LinearLayout.VERTICAL
|
||||
const val INDICATOR_RTL = 3
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.mogo.och.taxi.passenger.widget.indicator.enums
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Created by zhangpan on 2019-10-18.
|
||||
* Description:
|
||||
</pre> *
|
||||
*/
|
||||
interface IndicatorSlideMode {
|
||||
companion object {
|
||||
const val NORMAL = 0
|
||||
const val SMOOTH = 2
|
||||
const val WORM = 3
|
||||
const val SCALE = 4
|
||||
const val COLOR = 5
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.mogo.och.taxi.passenger.widget.indicator.enums
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Created by zhangpan on 2019-10-18.
|
||||
* Description:
|
||||
</pre> *
|
||||
*/
|
||||
interface IndicatorStyle {
|
||||
companion object {
|
||||
const val CIRCLE = 0
|
||||
const val DASH = 1 shl 1
|
||||
const val ROUND_RECT = 1 shl 2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.mogo.och.taxi.passenger.widget.indicator.option;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.mogo.och.taxi.passenger.R;
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.utils.IndicatorUtils;
|
||||
|
||||
public class AttrsController {
|
||||
|
||||
public static void initAttrs(@NonNull Context context, @Nullable AttributeSet attrs,
|
||||
IndicatorOptions indicatorOptions) {
|
||||
if (attrs != null) {
|
||||
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.IndicatorView);
|
||||
int indicatorSlideMode = typedArray.getInt(R.styleable.IndicatorView_vpi_slide_mode, 0);
|
||||
int indicatorStyle = typedArray.getInt(R.styleable.IndicatorView_vpi_style, 0);
|
||||
int checkedColor = typedArray.getColor(R.styleable.IndicatorView_vpi_slider_checked_color,
|
||||
Color.parseColor("#6C6D72"));
|
||||
int normalColor = typedArray.getColor(R.styleable.IndicatorView_vpi_slider_normal_color,
|
||||
Color.parseColor("#8C18171C"));
|
||||
int orientation = typedArray.getInt(R.styleable.IndicatorView_vpi_orientation, 0);
|
||||
float radius = typedArray.getDimension(R.styleable.IndicatorView_vpi_slider_radius,
|
||||
IndicatorUtils.dp2px(8));
|
||||
indicatorOptions.setCheckedColor(checkedColor);
|
||||
indicatorOptions.setNormalSliderColor(normalColor);
|
||||
indicatorOptions.setOrientation(orientation);
|
||||
indicatorOptions.setIndicatorStyle(indicatorStyle);
|
||||
indicatorOptions.setSlideMode(indicatorSlideMode);
|
||||
indicatorOptions.setSliderWidth(radius * 2, radius * 2);
|
||||
typedArray.recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.mogo.och.taxi.passenger.widget.indicator.option
|
||||
|
||||
import android.graphics.Color
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.annotation.AIndicatorOrientation
|
||||
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.annotation.AIndicatorSlideMode
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.annotation.AIndicatorStyle
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorOrientation
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.enums.IndicatorSlideMode
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.utils.IndicatorUtils
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Created by zhpan on 2019/11/20.
|
||||
* Description:Indicator的配置参数
|
||||
</pre> *
|
||||
*/
|
||||
class IndicatorOptions {
|
||||
|
||||
@AIndicatorOrientation
|
||||
var orientation = IndicatorOrientation.INDICATOR_HORIZONTAL
|
||||
|
||||
@AIndicatorStyle
|
||||
var indicatorStyle: Int = 0
|
||||
|
||||
/**
|
||||
* Indicator滑动模式,目前仅支持两种
|
||||
*
|
||||
* @see IndicatorSlideMode.NORMAL
|
||||
*
|
||||
* @see IndicatorSlideMode.SMOOTH
|
||||
*/
|
||||
@AIndicatorSlideMode
|
||||
var slideMode: Int = 0
|
||||
|
||||
/**
|
||||
* 页面size
|
||||
*/
|
||||
var pageSize: Int = 0
|
||||
|
||||
/**
|
||||
* 未选中时Indicator颜色
|
||||
*/
|
||||
var normalSliderColor: Int = 0
|
||||
|
||||
/**
|
||||
* 选中时Indicator颜色
|
||||
*/
|
||||
var checkedSliderColor: Int = 0
|
||||
|
||||
/**
|
||||
* Indicator间距
|
||||
*/
|
||||
var sliderGap: Float = 0f
|
||||
|
||||
var sliderHeight: Float = 0f
|
||||
get() = if (field > 0) field else normalSliderWidth / 2
|
||||
|
||||
var normalSliderWidth: Float = 0f
|
||||
|
||||
var checkedSliderWidth: Float = 0f
|
||||
|
||||
/**
|
||||
* 指示器当前位置
|
||||
*/
|
||||
var currentPosition: Int = 0
|
||||
|
||||
/**
|
||||
* 从一个点滑动到另一个点的进度
|
||||
*/
|
||||
var slideProgress: Float = 0f
|
||||
|
||||
var showIndicatorOneItem: Boolean = false
|
||||
|
||||
init {
|
||||
normalSliderWidth = IndicatorUtils.dp2px(8f)
|
||||
.toFloat()
|
||||
checkedSliderWidth = normalSliderWidth
|
||||
sliderGap = normalSliderWidth
|
||||
normalSliderColor = Color.parseColor("#8C18171C")
|
||||
checkedSliderColor = Color.parseColor("#8C6C6D72")
|
||||
slideMode = IndicatorSlideMode.NORMAL
|
||||
}
|
||||
|
||||
fun setCheckedColor(checkedColor: Int) {
|
||||
this.checkedSliderColor = checkedColor
|
||||
}
|
||||
|
||||
fun setSliderWidth(
|
||||
normalIndicatorWidth: Float,
|
||||
checkedIndicatorWidth: Float
|
||||
) {
|
||||
this.normalSliderWidth = normalIndicatorWidth
|
||||
this.checkedSliderWidth = checkedIndicatorWidth
|
||||
}
|
||||
|
||||
fun setSliderWidth(sliderWidth: Float) {
|
||||
setSliderWidth(sliderWidth, sliderWidth)
|
||||
}
|
||||
|
||||
fun setSliderColor(
|
||||
normalColor: Int,
|
||||
checkedColor: Int
|
||||
) {
|
||||
this.normalSliderColor = normalColor
|
||||
this.checkedSliderColor = checkedColor
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.mogo.och.taxi.passenger.widget.indicator.utils
|
||||
|
||||
import android.content.res.Resources
|
||||
|
||||
import com.mogo.och.taxi.passenger.widget.indicator.option.IndicatorOptions
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Created by zhangpan on 2020-01-20.
|
||||
* Description:
|
||||
</pre> *
|
||||
*/
|
||||
object IndicatorUtils {
|
||||
|
||||
@JvmStatic
|
||||
fun dp2px(dpValue: Float): Int {
|
||||
return (0.5f + dpValue * Resources.getSystem().displayMetrics.density).toInt()
|
||||
}
|
||||
|
||||
fun getCoordinateX(
|
||||
indicatorOptions: IndicatorOptions,
|
||||
maxDiameter: Float,
|
||||
index: Int
|
||||
): Float {
|
||||
val normalIndicatorWidth = indicatorOptions.normalSliderWidth
|
||||
return maxDiameter / 2 + (normalIndicatorWidth + indicatorOptions.sliderGap) * index
|
||||
}
|
||||
|
||||
fun getCoordinateY(maxDiameter: Float): Float {
|
||||
return maxDiameter / 2
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,21 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tv_mogo_consult"/>
|
||||
|
||||
<com.mogo.och.taxi.passenger.widget.indicator.IndicatorView
|
||||
android:id="@+id/indicatorView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/rv_video_playlist"
|
||||
android:layout_marginTop="95px"
|
||||
app:vpi_orientation="horizontal"
|
||||
app:vpi_slide_mode="scale"
|
||||
app:vpi_slider_checked_color="@color/taxi_p_traffic_light_red_color_up"
|
||||
app:vpi_slider_normal_color="@color/taxi_p_check_keyboard_input_field"
|
||||
app:vpi_slider_radius="@dimen/dp_20"
|
||||
app:vpi_style="round_rect" />
|
||||
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
31
OCH/mogo-och-taxi-passenger/src/main/res/values/attrs.xml
Normal file
31
OCH/mogo-och-taxi-passenger/src/main/res/values/attrs.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<declare-styleable name="IndicatorView">
|
||||
|
||||
<attr name="vpi_slider_checked_color" format="color" />
|
||||
<attr name="vpi_slider_normal_color" format="color" />
|
||||
<attr name="vpi_slider_radius" format="dimension" />
|
||||
<attr name="vpi_rtl" format="boolean" />
|
||||
|
||||
<attr name="vpi_orientation" format="enum">
|
||||
<enum name="horizontal" value="0" />
|
||||
<enum name="vertical" value="1" />
|
||||
<enum name="rtl" value="3"/>
|
||||
</attr>
|
||||
|
||||
<attr name="vpi_slide_mode" format="enum">
|
||||
<enum name="normal" value="0" />
|
||||
<enum name="smooth" value="2" />
|
||||
<enum name="worm" value="3" />
|
||||
<enum name="scale" value="4" />
|
||||
<enum name="color" value="5" />
|
||||
</attr>
|
||||
|
||||
<attr name="vpi_style" format="enum">
|
||||
<enum name="circle" value="0" />
|
||||
<enum name="dash" value="2" />
|
||||
<enum name="round_rect" value="4" />
|
||||
</attr>
|
||||
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user