Android實(shí)現(xiàn)底部滾輪式選擇彈跳框
本文實(shí)例為大家分享了Android實(shí)現(xiàn)底部滾輪式選擇彈跳框的具體代碼,供大家參考,具體內(nèi)容如下
先看效果:
調(diào)用方法:
SlideDialog slideDialog = new SlideDialog(this, list, false, false); slideDialog.setOnSelectClickListener(new SlideDialog.OnSelectListener() { ? ? ? @Override ? ? ? public void onCancel() { ? ? ? ? ? Toast.makeText(GroupFormListActivity.this, "未選擇", Toast.LENGTH_SHORT).show(); ? ? ? ? ? ? } ? ? ? ? @Override ? ? ? public void onAgree(String txt) { ? ? ? ? ? Toast.makeText(GroupFormListActivity.this, "已選中", Toast.LENGTH_SHORT).show(); ? ? ? ? ? ? } ? ? ? ? }); slideDialog.show();
自定義SlideDialog
package xxx.xxx.xxx.xxx; ? import android.app.Dialog; import android.content.Context; import android.os.Bundle; import android.view.Gravity; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.TextView; ? import androidx.annotation.NonNull; ? import com.txh.yunyao.R; import com.txh.yunyao.common.views.EasyPickerView; ? import java.util.ArrayList; import java.util.List; ? /** ?* 底部滑動(dòng)選擇彈跳框 ?*/ public class SlideDialog extends Dialog { ? ? private boolean isCancelable = false; ? ? private boolean isBackCancelable = false; ? ? private Context mContext; ? //上下文 ? ? private List<String> list = new ArrayList<>(0); //數(shù)據(jù) ? ? private int selectPos; //默認(rèn)選中位置 ? ? private OnSelectListener mSelectListener; //監(jiān)聽(tīng) ? ? ? public SlideDialog(@NonNull Context context, int view, List<String> list, boolean isCancelable, boolean isBackCancelable) { ? ? ? ? super(context, R.style.SlideDialog); ? ? ? ? this.mContext = context; ? ? ? ? this.isCancelable = isCancelable; ? ? ? ? this.isBackCancelable = isBackCancelable; ? ? ? ? this.list = list; ? ? ? ? this.selectPos = 0; ? ? } ? ? ? @Override ? ? protected void onCreate(Bundle savedInstanceState) { ? ? ? ? super.onCreate(savedInstanceState); ? ? ? ? //設(shè)置View ? ? ? ? setContentView(R.layout.select_slide_template); ? ? ? ? //設(shè)置點(diǎn)擊物理返回鍵是否可關(guān)閉彈框 ? ? ? ? setCancelable(isCancelable); ? ? ? ? //設(shè)置點(diǎn)擊彈框外是否可關(guān)閉彈框 ? ? ? ? setCanceledOnTouchOutside(isBackCancelable); ? ? ? ? //設(shè)置view顯示位置 ? ? ? ? Window window = this.getWindow(); ? ? ? ? window.setGravity(Gravity.BOTTOM); ? ? ? ? WindowManager.LayoutParams params = window.getAttributes(); ? ? ? ? params.width = WindowManager.LayoutParams.MATCH_PARENT; ? ? ? ? params.height = WindowManager.LayoutParams.WRAP_CONTENT; ? ? ? ? window.setAttributes(params); ? ? ? ? //初始化控件 ? ? ? ? TextView tv_cancel = findViewById(R.id.tv_cancel); ? ? ? ? TextView tv_agree = findViewById(R.id.tv_agree); ? ? ? ? EasyPickerView pickerView = findViewById(R.id.pickerView); ? ? ? ? //取消點(diǎn)擊事件 ? ? ? ? tv_cancel.setOnClickListener(new View.OnClickListener() { ? ? ? ? ? ? @Override ? ? ? ? ? ? public void onClick(View v) { ? ? ? ? ? ? ? ? //取消 ? ? ? ? ? ? ? ? mSelectListener.onCancel(); ? ? ? ? ? ? ? ? dismiss(); ? ? ? ? ? ? } ? ? ? ? }); ? ? ? ? //確認(rèn)點(diǎn)擊事件 ? ? ? ? tv_agree.setOnClickListener(new View.OnClickListener() { ? ? ? ? ? ? @Override ? ? ? ? ? ? public void onClick(View v) { ? ? ? ? ? ? ? ? //確認(rèn) ? ? ? ? ? ? ? ? mSelectListener.onAgree(list.get(selectPos)); ? ? ? ? ? ? ? ? dismiss(); ? ? ? ? ? ? } ? ? ? ? }); ? ? ? ? //設(shè)置數(shù)據(jù) ? ? ? ? pickerView.setDataList(list); ? ? ? ? //監(jiān)聽(tīng)數(shù)據(jù) ? ? ? ? pickerView.setOnScrollChangedListener(new EasyPickerView.OnScrollChangedListener() { ? ? ? ? ? ? @Override ? ? ? ? ? ? public void onScrollChanged(int curIndex) { ? ? ? ? ? ? ? ? //滾動(dòng)時(shí)選中項(xiàng)發(fā)生變化 ? ? ? ? ? ? ? } ? ? ? ? ? ? ? @Override ? ? ? ? ? ? public void onScrollFinished(int curIndex) { ? ? ? ? ? ? ? ? //滾動(dòng)結(jié)束 ? ? ? ? ? ? ? ? selectPos = curIndex; ? ? ? ? ? ? ? } ? ? ? ? }); ? ? ? } ? ? ? public interface OnSelectListener { ? ? ? ? //取消 ? ? ? ? void onCancel(); ? ? ? ? //確認(rèn) ? ? ? ? void onAgree(String txt); ? ? } ? ? ? public void setOnSelectClickListener(OnSelectListener listener) { ? ? ? ? this.mSelectListener = listener; ? ? } }
R.style.SlideDialog
<style name="SlideDialog" parent="@android:style/Theme.Holo.Dialog"> ? ? ? ? <!-- 是否有邊框 --> ? ? ? ? <item name="android:windowFrame">@null</item> ? ? ? ? <!--是否在懸浮Activity之上 ?--> ? ? ? ? <item name="android:windowIsFloating">true</item> ? ? ? ? <!-- 標(biāo)題 --> ? ? ? ? <item name="android:windowNoTitle">true</item> ? ? ? ? <!--陰影 ?--> ? ? ? ? <item name="android:windowIsTranslucent">true</item><!--半透明--> ? ? ? ? <!--背景透明--> ? ? ? ? <item name="android:windowBackground">@android:color/transparent</item> ? ? ? ? <!-- 還可以加入一些彈出和退出的動(dòng)畫 (lan)--> </style>
R.layout.select_slide_template
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" ? ? android:layout_width="match_parent" ? ? android:layout_height="wrap_content" ? ? xmlns:app="http://schemas.android.com/apk/res-auto" ? ? android:background="@color/white" ? ? android:orientation="vertical"> ? ? ? <RelativeLayout ? ? ? ? android:layout_width="match_parent" ? ? ? ? android:layout_height="wrap_content" ? ? ? ? android:layout_marginLeft="@dimen/dp_10" ? ? ? ? android:layout_marginRight="@dimen/dp_10" ? ? ? ? android:paddingTop="@dimen/dp_10" ? ? ? ? android:paddingLeft="@dimen/dp_15" ? ? ? ? android:paddingRight="@dimen/dp_15"> ? ? ? ? ? <TextView ? ? ? ? ? ? android:id="@+id/tv_cancel" ? ? ? ? ? ? android:layout_width="wrap_content" ? ? ? ? ? ? android:layout_height="wrap_content" ? ? ? ? ? ? android:text="@string/picture_cancel" ? ? ? ? ? ? android:padding="3dp" ? ? ? ? ? ? android:textColor="@color/black" /> ? ? ? ? ? <TextView ? ? ? ? ? ? android:id="@+id/tv_agree" ? ? ? ? ? ? android:layout_width="wrap_content" ? ? ? ? ? ? android:layout_height="wrap_content" ? ? ? ? ? ? android:layout_alignParentRight="true" ? ? ? ? ? ? android:text="@string/picture_confirm" ? ? ? ? ? ? android:padding="3dp" ? ? ? ? ? ? android:textColor="@color/black" /> ? ? </RelativeLayout> ? ? ? <com.txh.yunyao.common.views.EasyPickerView ? ? ? ? android:id="@+id/pickerView" ? ? ? ? android:layout_width="match_parent" ? ? ? ? android:layout_height="wrap_content" ? ? ? ? app:epvMaxShowNum="3" ? ? ? ? android:layout_marginBottom="@dimen/dp_15" ? ? ? ? android:layout_marginTop="@dimen/dp_15" ? ? ? ? app:epvTextColor="@color/black" ? ? ? ? app:epvTextPadding="@dimen/dp_10" ? ? ? ? app:epvRecycleMode="true" ? ? ? ? app:epvTextSize="14dp"/> </LinearLayout>
自定義EasyPickerView支持以下幾個(gè)屬性:
- epvTextSize:字符的大小
- epvTextColor:字符的顏色
- epvTextPadding:字符的間距
- epvTextMaxScale:中間字符縮放的最大值
- epvTextMinAlpha:兩端字符最小alpha值
- epvRecycleMode:是否為循環(huán)模式
- epvMaxShowNum:顯示多少個(gè)字符
自定義EasyPickerView
package xxx.xxx.xxx.xxx.xxx; ? import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.text.TextPaint; import android.util.AttributeSet; import android.util.TypedValue; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import android.widget.Scroller; ? import com.txh.yunyao.R; ? import java.util.ArrayList; import java.util.List; ? /** ?* 滾輪視圖,可設(shè)置是否循環(huán)模式,實(shí)現(xiàn)OnScrollChangedListener接口以監(jiān)聽(tīng)滾輪變化 ?*/ public class EasyPickerView extends View { ? ? ? // 文字大小 ? ? private int textSize; ? ? // 顏色,默認(rèn)Color.BLACK ? ? private int textColor; ? ? // 文字之間的間隔,默認(rèn)10dp ? ? private int textPadding; ? ? // 文字最大放大比例,默認(rèn)2.0f ? ? private float textMaxScale; ? ? // 文字最小alpha值,范圍0.0f~1.0f,默認(rèn)0.4f ? ? private float textMinAlpha; ? ? // 是否循環(huán)模式,默認(rèn)是 ? ? private boolean isRecycleMode; ? ? // 正常狀態(tài)下最多顯示幾個(gè)文字,默認(rèn)3(偶數(shù)時(shí),邊緣的文字會(huì)截?cái)啵? ? ? private int maxShowNum; ? ? ? private TextPaint textPaint; ? ? private Paint.FontMetrics fm; ? ? ? private Scroller scroller; ? ? private VelocityTracker velocityTracker; ? ? private int minimumVelocity; ? ? private int maximumVelocity; ? ? private int scaledTouchSlop; ? ? ? // 數(shù)據(jù) ? ? private List<String> dataList = new ArrayList<>(0); ? ? // 中間x坐標(biāo) ? ? private int cx; ? ? // 中間y坐標(biāo) ? ? private int cy; ? ? // 文字最大寬度 ? ? private float maxTextWidth; ? ? // 文字高度 ? ? private int textHeight; ? ? // 實(shí)際內(nèi)容寬度 ? ? private int contentWidth; ? ? // 實(shí)際內(nèi)容高度 ? ? private int contentHeight; ? ? ? // 按下時(shí)的y坐標(biāo) ? ? private float downY; ? ? // 本次滑動(dòng)的y坐標(biāo)偏移值 ? ? private float offsetY; ? ? // 在fling之前的offsetY ? ? private float oldOffsetY; ? ? // 當(dāng)前選中項(xiàng) ? ? private int curIndex; ? ? private int offsetIndex; ? ? ? // 回彈距離 ? ? private float bounceDistance; ? ? // 是否正處于滑動(dòng)狀態(tài) ? ? private boolean isSliding = false; ? ? ? public EasyPickerView(Context context) { ? ? ? ? this(context, null); ? ? } ? ? ? public EasyPickerView(Context context, AttributeSet attrs) { ? ? ? ? this(context, attrs, 0); ? ? } ? ? ? public EasyPickerView(Context context, AttributeSet attrs, int defStyleAttr) { ? ? ? ? super(context, attrs, defStyleAttr); ? ? ? ? ? TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.EasyPickerView, defStyleAttr, 0); ? ? ? ? textSize = a.getDimensionPixelSize(R.styleable.EasyPickerView_epvTextSize, (int) TypedValue.applyDimension( ? ? ? ? ? ? ? ? TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics())); ? ? ? ? textColor = a.getColor(R.styleable.EasyPickerView_epvTextColor, Color.BLACK); ? ? ? ? textPadding = a.getDimensionPixelSize(R.styleable.EasyPickerView_epvTextPadding, (int) TypedValue.applyDimension( ? ? ? ? ? ? ? ? TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics())); ? ? ? ? textMaxScale = a.getFloat(R.styleable.EasyPickerView_epvTextMaxScale, 2.0f); ? ? ? ? textMinAlpha = a.getFloat(R.styleable.EasyPickerView_epvTextMinAlpha, 0.4f); ? ? ? ? isRecycleMode = a.getBoolean(R.styleable.EasyPickerView_epvRecycleMode, true); ? ? ? ? maxShowNum = a.getInteger(R.styleable.EasyPickerView_epvMaxShowNum, 3); ? ? ? ? a.recycle(); ? ? ? ? ? textPaint = new TextPaint(); ? ? ? ? textPaint.setColor(textColor); ? ? ? ? textPaint.setTextSize(textSize); ? ? ? ? textPaint.setAntiAlias(true); ? ? ? ? fm = textPaint.getFontMetrics(); ? ? ? ? textHeight = (int) (fm.bottom - fm.top); ? ? ? ? ? scroller = new Scroller(context); ? ? ? ? minimumVelocity = ViewConfiguration.get(getContext()).getScaledMinimumFlingVelocity(); ? ? ? ? maximumVelocity = ViewConfiguration.get(getContext()).getScaledMaximumFlingVelocity(); ? ? ? ? scaledTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); ? ? } ? ? ? @Override ? ? protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { ? ? ? ? int mode = MeasureSpec.getMode(widthMeasureSpec); ? ? ? ? int width = MeasureSpec.getSize(widthMeasureSpec); ? ? ? ? contentWidth = (int) (maxTextWidth * textMaxScale + getPaddingLeft() + getPaddingRight()); ? ? ? ? if (mode != MeasureSpec.EXACTLY) { // wrap_content ? ? ? ? ? ? width = contentWidth; ? ? ? ? } ? ? ? ? ? mode = MeasureSpec.getMode(heightMeasureSpec); ? ? ? ? int height = MeasureSpec.getSize(heightMeasureSpec); ? ? ? ? contentHeight = textHeight * maxShowNum + textPadding * maxShowNum; ? ? ? ? if (mode != MeasureSpec.EXACTLY) { // wrap_content ? ? ? ? ? ? height = contentHeight + getPaddingTop() + getPaddingBottom(); ? ? ? ? } ? ? ? ? ? cx = width / 2; ? ? ? ? cy = height / 2; ? ? ? ? ? setMeasuredDimension(width, height); ? ? } ? ? ? @Override ? ? public boolean dispatchTouchEvent(MotionEvent event) { ? ? ? ? getParent().requestDisallowInterceptTouchEvent(true); ? ? ? ? return super.dispatchTouchEvent(event); ? ? } ? ? ? @Override ? ? public boolean onTouchEvent(MotionEvent event) { ? ? ? ? addVelocityTracker(event); ? ? ? ? switch (event.getAction()) { ? ? ? ? ? ? case MotionEvent.ACTION_DOWN: ? ? ? ? ? ? ? ? if (!scroller.isFinished()) { ? ? ? ? ? ? ? ? ? ? scroller.forceFinished(true); ? ? ? ? ? ? ? ? ? ? finishScroll(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? downY = event.getY(); ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? case MotionEvent.ACTION_MOVE: ? ? ? ? ? ? ? ? offsetY = event.getY() - downY; ? ? ? ? ? ? ? ? if (isSliding || Math.abs(offsetY) > scaledTouchSlop) { ? ? ? ? ? ? ? ? ? ? isSliding = true; ? ? ? ? ? ? ? ? ? ? reDraw(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? case MotionEvent.ACTION_UP: ? ? ? ? ? ? ? ? int scrollYVelocity = 2 * getScrollYVelocity() / 3; ? ? ? ? ? ? ? ? if (Math.abs(scrollYVelocity) > minimumVelocity) { ? ? ? ? ? ? ? ? ? ? oldOffsetY = offsetY; ? ? ? ? ? ? ? ? ? ? scroller.fling(0, 0, 0, scrollYVelocity, 0, 0, -Integer.MAX_VALUE, Integer.MAX_VALUE); ? ? ? ? ? ? ? ? ? ? invalidate(); ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? finishScroll(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? // 沒(méi)有滑動(dòng),則判斷點(diǎn)擊事件 ? ? ? ? ? ? ? ? if (!isSliding) { ? ? ? ? ? ? ? ? ? ? if (downY < contentHeight / 3) ? ? ? ? ? ? ? ? ? ? ? ? moveBy(-1); ? ? ? ? ? ? ? ? ? ? else if (downY > 2 * contentHeight / 3) ? ? ? ? ? ? ? ? ? ? ? ? moveBy(1); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? isSliding = false; ? ? ? ? ? ? ? ? recycleVelocityTracker(); ? ? ? ? ? ? ? ? break; ? ? ? ? } ? ? ? ? return true; ? ? } ? ? ? @Override ? ? protected void onDraw(Canvas canvas) { ? ? ? ? if (null != dataList && dataList.size() > 0) { ? ? ? ? ? ? canvas.clipRect( ? ? ? ? ? ? ? ? ? ? cx - contentWidth / 2, ? ? ? ? ? ? ? ? ? ? cy - contentHeight / 2, ? ? ? ? ? ? ? ? ? ? cx + contentWidth / 2, ? ? ? ? ? ? ? ? ? ? cy + contentHeight / 2 ? ? ? ? ? ? ); ? ? ? ? ? ? ? // 繪制文字,從當(dāng)前中間項(xiàng)往前、后一共繪制maxShowNum個(gè)字 ? ? ? ? ? ? int size = dataList.size(); ? ? ? ? ? ? int centerPadding = textHeight + textPadding; ? ? ? ? ? ? int half = maxShowNum / 2 + 1; ? ? ? ? ? ? for (int i = -half; i <= half; i++) { ? ? ? ? ? ? ? ? int index = curIndex - offsetIndex + i; ? ? ? ? ? ? ? ? ? if (isRecycleMode) { ? ? ? ? ? ? ? ? ? ? if (index < 0) ? ? ? ? ? ? ? ? ? ? ? ? index = (index + 1) % dataList.size() + dataList.size() - 1; ? ? ? ? ? ? ? ? ? ? else if (index > dataList.size() - 1) ? ? ? ? ? ? ? ? ? ? ? ? index = index % dataList.size(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? if (index >= 0 && index < size) { ? ? ? ? ? ? ? ? ? ? // 計(jì)算每個(gè)字的中間y坐標(biāo) ? ? ? ? ? ? ? ? ? ? int tempY = cy + i * centerPadding; ? ? ? ? ? ? ? ? ? ? tempY += offsetY % centerPadding; ? ? ? ? ? ? ? ? ? ? ? // 根據(jù)每個(gè)字中間y坐標(biāo)到cy的距離,計(jì)算出scale值 ? ? ? ? ? ? ? ? ? ? float scale = 1.0f - (1.0f * Math.abs(tempY - cy) / centerPadding); ? ? ? ? ? ? ? ? ? ? ? // 根據(jù)textMaxScale,計(jì)算出tempScale值,即實(shí)際text應(yīng)該放大的倍數(shù),范圍 1~textMaxScale ? ? ? ? ? ? ? ? ? ? float tempScale = scale * (textMaxScale - 1.0f) + 1.0f; ? ? ? ? ? ? ? ? ? ? tempScale = tempScale < 1.0f ? 1.0f : tempScale; ? ? ? ? ? ? ? ? ? ? ? // 計(jì)算文字alpha值 ? ? ? ? ? ? ? ? ? ? float textAlpha = textMinAlpha; ? ? ? ? ? ? ? ? ? ? if (textMaxScale != 1) { ? ? ? ? ? ? ? ? ? ? ? ? float tempAlpha = (tempScale - 1) / (textMaxScale - 1); ? ? ? ? ? ? ? ? ? ? ? ? textAlpha = (1 - textMinAlpha) * tempAlpha + textMinAlpha; ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? textPaint.setTextSize(textSize * tempScale); ? ? ? ? ? ? ? ? ? ? textPaint.setAlpha((int) (255 * textAlpha)); ? ? ? ? ? ? ? ? ? ? ? // 繪制 ? ? ? ? ? ? ? ? ? ? Paint.FontMetrics tempFm = textPaint.getFontMetrics(); ? ? ? ? ? ? ? ? ? ? String text = dataList.get(index); ? ? ? ? ? ? ? ? ? ? float textWidth = textPaint.measureText(text); ? ? ? ? ? ? ? ? ? ? canvas.drawText(text, cx - textWidth / 2, tempY - (tempFm.ascent + tempFm.descent) / 2, textPaint); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } ? ? } ? ? ? @Override ? ? public void computeScroll() { ? ? ? ? if (scroller.computeScrollOffset()) { ? ? ? ? ? ? offsetY = oldOffsetY + scroller.getCurrY(); ? ? ? ? ? ? ? if (!scroller.isFinished()) ? ? ? ? ? ? ? ? reDraw(); ? ? ? ? ? ? else ? ? ? ? ? ? ? ? finishScroll(); ? ? ? ? } ? ? } ? ? ? private void addVelocityTracker(MotionEvent event) { ? ? ? ? if (velocityTracker == null) ? ? ? ? ? ? velocityTracker = VelocityTracker.obtain(); ? ? ? ? ? velocityTracker.addMovement(event); ? ? } ? ? ? private void recycleVelocityTracker() { ? ? ? ? if (velocityTracker != null) { ? ? ? ? ? ? velocityTracker.recycle(); ? ? ? ? ? ? velocityTracker = null; ? ? ? ? } ? ? } ? ? ? private int getScrollYVelocity() { ? ? ? ? velocityTracker.computeCurrentVelocity(1000, maximumVelocity); ? ? ? ? int velocity = (int) velocityTracker.getYVelocity(); ? ? ? ? return velocity; ? ? } ? ? ? private void reDraw() { ? ? ? ? // curIndex需要偏移的量 ? ? ? ? int i = (int) (offsetY / (textHeight + textPadding)); ? ? ? ? if (isRecycleMode || (curIndex - i >= 0 && curIndex - i < dataList.size())) { ? ? ? ? ? ? if (offsetIndex != i) { ? ? ? ? ? ? ? ? offsetIndex = i; ? ? ? ? ? ? ? ? ? if (null != onScrollChangedListener) ? ? ? ? ? ? ? ? ? ? onScrollChangedListener.onScrollChanged(getNowIndex(-offsetIndex)); ? ? ? ? ? ? } ? ? ? ? ? ? postInvalidate(); ? ? ? ? } else { ? ? ? ? ? ? finishScroll(); ? ? ? ? } ? ? } ? ? ? private void finishScroll() { ? ? ? ? // 判斷結(jié)束滑動(dòng)后應(yīng)該停留在哪個(gè)位置 ? ? ? ? int centerPadding = textHeight + textPadding; ? ? ? ? float v = offsetY % centerPadding; ? ? ? ? if (v > 0.5f * centerPadding) ? ? ? ? ? ? ++offsetIndex; ? ? ? ? else if (v < -0.5f * centerPadding) ? ? ? ? ? ? --offsetIndex; ? ? ? ? ? // 重置curIndex ? ? ? ? curIndex = getNowIndex(-offsetIndex); ? ? ? ? ? // 計(jì)算回彈的距離 ? ? ? ? bounceDistance = offsetIndex * centerPadding - offsetY; ? ? ? ? offsetY += bounceDistance; ? ? ? ? ? // 更新 ? ? ? ? if (null != onScrollChangedListener) ? ? ? ? ? ? onScrollChangedListener.onScrollFinished(curIndex); ? ? ? ? ? // 重繪 ? ? ? ? reset(); ? ? ? ? postInvalidate(); ? ? } ? ? ? private int getNowIndex(int offsetIndex) { ? ? ? ? int index = curIndex + offsetIndex; ? ? ? ? if (isRecycleMode) { ? ? ? ? ? ? if (index < 0) ? ? ? ? ? ? ? ? index = (index + 1) % dataList.size() + dataList.size() - 1; ? ? ? ? ? ? else if (index > dataList.size() - 1) ? ? ? ? ? ? ? ? index = index % dataList.size(); ? ? ? ? } else { ? ? ? ? ? ? if (index < 0) ? ? ? ? ? ? ? ? index = 0; ? ? ? ? ? ? else if (index > dataList.size() - 1) ? ? ? ? ? ? ? ? index = dataList.size() - 1; ? ? ? ? } ? ? ? ? return index; ? ? } ? ? ? private void reset() { ? ? ? ? offsetY = 0; ? ? ? ? oldOffsetY = 0; ? ? ? ? offsetIndex = 0; ? ? ? ? bounceDistance = 0; ? ? } ? ? ? /** ? ? ?* 設(shè)置要顯示的數(shù)據(jù) ? ? ?* ? ? ?* @param dataList 要顯示的數(shù)據(jù) ? ? ?*/ ? ? public void setDataList(List<String> dataList) { ? ? ? ? this.dataList.clear(); ? ? ? ? this.dataList.addAll(dataList); ? ? ? ? ? // 更新maxTextWidth ? ? ? ? if (null != dataList && dataList.size() > 0) { ? ? ? ? ? ? int size = dataList.size(); ? ? ? ? ? ? for (int i = 0; i < size; i++) { ? ? ? ? ? ? ? ? float tempWidth = textPaint.measureText(dataList.get(i)); ? ? ? ? ? ? ? ? if (tempWidth > maxTextWidth) ? ? ? ? ? ? ? ? ? ? maxTextWidth = tempWidth; ? ? ? ? ? ? } ? ? ? ? ? ? curIndex = 0; ? ? ? ? } ? ? ? ? requestLayout(); ? ? ? ? invalidate(); ? ? } ? ? ? /** ? ? ?* 獲取當(dāng)前狀態(tài)下,選中的下標(biāo) ? ? ?* ? ? ?* @return 選中的下標(biāo) ? ? ?*/ ? ? public int getCurIndex() { ? ? ? ? return getNowIndex(-offsetIndex); ? ? } ? ? ? /** ? ? ?* 滾動(dòng)到指定位置 ? ? ?* ? ? ?* @param index 需要滾動(dòng)到的指定位置 ? ? ?*/ ? ? public void moveTo(int index) { ? ? ? ? if (index < 0 || index >= dataList.size() || curIndex == index) ? ? ? ? ? ? return; ? ? ? ? ? if (!scroller.isFinished()) ? ? ? ? ? ? scroller.forceFinished(true); ? ? ? ? ? finishScroll(); ? ? ? ? ? int dy = 0; ? ? ? ? int centerPadding = textHeight + textPadding; ? ? ? ? if (!isRecycleMode) { ? ? ? ? ? ? dy = (curIndex - index) * centerPadding; ? ? ? ? } else { ? ? ? ? ? ? int offsetIndex = curIndex - index; ? ? ? ? ? ? int d1 = Math.abs(offsetIndex) * centerPadding; ? ? ? ? ? ? int d2 = (dataList.size() - Math.abs(offsetIndex)) * centerPadding; ? ? ? ? ? ? ? if (offsetIndex > 0) { ? ? ? ? ? ? ? ? if (d1 < d2) ? ? ? ? ? ? ? ? ? ? dy = d1; // ascent ? ? ? ? ? ? ? ? else ? ? ? ? ? ? ? ? ? ? dy = -d2; // descent ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? if (d1 < d2) ? ? ? ? ? ? ? ? ? ? dy = -d1; // descent ? ? ? ? ? ? ? ? else ? ? ? ? ? ? ? ? ? ? dy = d2; // ascent ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? scroller.startScroll(0, 0, 0, dy, 500); ? ? ? ? invalidate(); ? ? } ? ? ? /** ? ? ?* 滾動(dòng)指定的偏移量 ? ? ?* ? ? ?* @param offsetIndex 指定的偏移量 ? ? ?*/ ? ? public void moveBy(int offsetIndex) { ? ? ? ? moveTo(getNowIndex(offsetIndex)); ? ? } ? ? ? /** ? ? ?* 滾動(dòng)發(fā)生變化時(shí)的回調(diào)接口 ? ? ?*/ ? ? public interface OnScrollChangedListener { ? ? ? ? public void onScrollChanged(int curIndex); ? ? ? ? ? public void onScrollFinished(int curIndex); ? ? } ? ? ? private OnScrollChangedListener onScrollChangedListener; ? ? ? public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) { ? ? ? ? this.onScrollChangedListener = onScrollChangedListener; ? ? } }
attrs中 EasyPickerView配置
<declare-styleable name="EasyPickerView"> ? ? <attr name="epvTextSize" format="dimension"/> ? ? <attr name="epvTextColor" format="color"/> ? ? <attr name="epvTextPadding" format="dimension"/> ? ? <attr name="epvTextMaxScale" format="float"/> ? ? <attr name="epvTextMinAlpha" format="float"/> ? ? <attr name="epvRecycleMode" format="boolean"/> ? ? <attr name="epvMaxShowNum" format="integer"/> </declare-styleable>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android仿Boss直聘文本日期混合滾輪選擇器示例
- Android 實(shí)現(xiàn)IOS 滾輪選擇控件的實(shí)例(源碼下載)
- Android滾輪選擇時(shí)間控件使用詳解
- Android高仿IOS 滾輪選擇控件
- 輕松實(shí)現(xiàn)可擴(kuò)展自定義的Android滾輪時(shí)間選擇控件
- Android實(shí)現(xiàn)底部圖片選擇Dialog
- Android 實(shí)現(xiàn)IOS選擇拍照相冊(cè)底部彈出的實(shí)例
- Android 仿京東商城底部布局的選擇效果(Selector 選擇器的實(shí)現(xiàn))
- Android開(kāi)發(fā)中實(shí)現(xiàn)IOS風(fēng)格底部選擇器(支持時(shí)間 日期 自定義)
相關(guān)文章
Android點(diǎn)擊Button實(shí)現(xiàn)功能的幾種方法總結(jié)
當(dāng)Button有多個(gè)或者Button的使用次數(shù)很多時(shí),我們需要采用綁定監(jiān)聽(tīng)器的做法,其實(shí),綁定監(jiān)聽(tīng)器也有幾種方法,不過(guò),我在這里就不一一列舉了,畢竟那些方法在實(shí)際的應(yīng)用中也不常見(jiàn)2013-10-10Android使用RecyclerView實(shí)現(xiàn)今日頭條頻道管理功能
這篇文章主要為大家詳細(xì)介紹了Android使用RecyclerView實(shí)現(xiàn)今日頭條頻道管理功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07Android如何調(diào)用系統(tǒng)相機(jī)拍照
這篇文章主要為大家詳細(xì)介紹了Android如何調(diào)用系統(tǒng)相機(jī)拍照的相關(guān)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09AFURLSessionManager 上傳下載使用代碼說(shuō)明
本文通過(guò)代碼給大家介紹了AFURLSessionManager 上傳下載使用說(shuō)明,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-09-09解決Android Device Monitor 的 File Explorer 中無(wú)法打開(kāi)某些文件夾的問(wèn)題
這篇文章主要介紹了解決Android Device Monitor 的 File Explorer 中無(wú)法打開(kāi)某些文件夾的問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04

配置android開(kāi)發(fā)環(huán)境時(shí)出現(xiàn)eclipse獲取不到ADT的解決方法

AndroidSDK Support自帶夜間、日間模式切換詳解