首页 > 系统 > Android > 正文

Android自定义控件实现按钮滚动选择效果

2019-10-21 21:45:28
字体:
来源:转载
供稿:网友

本文实例为大家分享了Android实现按钮滚动选择效果的具体代码,供大家参考,具体内容如下

效果图

Android,自定义控件,按钮,滚动选择

代码实现

package com.demo.ui.view;import android.annotation.TargetApi;import android.content.Context;import android.os.Build;import android.os.Handler;import android.support.v4.content.ContextCompat;import android.view.Gravity;import android.view.MotionEvent;import android.view.View;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.RelativeLayout;import android.widget.TextView;import com.demo.R;import com.demo.factory.Axis;import com.demo.utils.LogUtils;import java.util.ArrayList;import java.util.List;public class AirTemperatureView extends RelativeLayout{ private Context context; private TextView tv; private TextView tv_middle; // private TextView tv_middle_small; private RelativeLayout Auto_layout; private StringScrollPicker stringScrollPicker; private List<CharSequence> newList; private ImageView img; private ImageView img_left; private ImageView img_right; private int mPosition; private Handler handler = new Handler(); /** * 延迟线程,看是否还有下一个字符输入 */ private Runnable delayRun = new Runnable() { @Override public void run() {  stringScrollPicker.setVisibility(INVISIBLE);  img.setBackgroundResource(R.drawable.air_temp_bg);  tv_middle.setText(newList.get(mPosition));  //tv.setText("电池剩余"+newList.get(mPosition)+"%提醒你");  tv_middle.setVisibility(VISIBLE);  img_right.setVisibility(VISIBLE);  img_left.setVisibility(VISIBLE);  if(mListener != null) {  mListener.setAirTemper(mPosition+18);  }  LogUtils.e("空调刷新===","温度"); } }; public AirTemperatureView(Context context){ super(context); this.context = context; init(); } @TargetApi(Build.VERSION_CODES.M) public void init(){ super.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, Axis.scaleX(230))); LinearLayout parent = new LinearLayout(context); parent.setOrientation(LinearLayout.VERTICAL); LayoutParams parent_Params = new LayoutParams(LayoutParams.MATCH_PARENT, Axis.scaleX(230)); super.addView(parent,parent_Params); RelativeLayout tv_layout = new RelativeLayout(context); LinearLayout.LayoutParams tv_layout_Params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, Axis.scaleX(50)); parent.addView(tv_layout,tv_layout_Params); tv = new TextView(context); tv.setText("温度"); tv.setTextSize(Axis.scaleTextSize(36)); tv.setTextColor(ContextCompat.getColor(context, R.color.white_70_color));// LayoutParams tv_Params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); tv_Params.addRule(RelativeLayout.CENTER_IN_PARENT); tv_layout.addView(tv,tv_Params); /**  * 滑动选择器  */ Auto_layout = new RelativeLayout(context); LinearLayout.LayoutParams Auto_layout_Params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, Axis.scaleX(150)); Auto_layout_Params.setMargins(0,Axis.scaleX(30),0,0); parent.addView(Auto_layout,Auto_layout_Params); img = new ImageView(context); img.setId(R.id.EleRemindImage); img.setBackgroundResource(R.drawable.air_temp_bg); LayoutParams img_Params = new LayoutParams(Axis.scaleX(150), Axis.scaleX(150)); img_Params.addRule(RelativeLayout.CENTER_IN_PARENT); Auto_layout.addView(img,img_Params); img_left = new ImageView(context); img_left.setBackgroundResource(R.drawable.battery_point); LayoutParams img_left_Params = new LayoutParams(Axis.scaleX(14), Axis.scaleX(14)); img_left_Params.addRule(RelativeLayout.CENTER_VERTICAL); img_left_Params.addRule(RelativeLayout.LEFT_OF,R.id.EleRemindImage); img_left_Params.setMargins(0,0,Axis.scaleX(134),0); Auto_layout.addView(img_left,img_left_Params); img_right = new ImageView(context); img_right.setBackgroundResource(R.drawable.battery_point); LayoutParams img_right_Params = new LayoutParams(Axis.scaleX(14), Axis.scaleX(14)); img_right_Params.addRule(RelativeLayout.CENTER_VERTICAL); img_right_Params.addRule(RelativeLayout.RIGHT_OF,R.id.EleRemindImage); img_right_Params.setMargins(Axis.scaleX(134),0,0,0); Auto_layout.addView(img_right,img_right_Params); tv_middle = new TextView(context); tv_middle.setTextSize(Axis.scaleTextSize(64)); tv_middle.setGravity(Gravity.CENTER); tv_middle.setTextColor(0xFFFFFFFF); LayoutParams tv_middle_Params = new LayoutParams(Axis.scaleX(150), Axis.scaleX(150)); tv_middle_Params.addRule(RelativeLayout.CENTER_IN_PARENT); Auto_layout.addView(tv_middle,tv_middle_Params); newList = new ArrayList<>(); newList.add("18"); newList.add("19"); newList.add("20"); newList.add("21"); newList.add("22"); newList.add("23"); newList.add("24"); newList.add("25"); newList.add("26"); newList.add("27"); newList.add("28"); newList.add("29"); newList.add("30"); newList.add("31"); newList.add("32"); tv_middle.setText(newList.get(0)); stringScrollPicker = new StringScrollPicker(context); stringScrollPicker.setHorizontal(true); stringScrollPicker.setVisibleItemCount(5);//可见5个 第3个 (3-1)个位中间 stringScrollPicker.setCenterPosition(2); stringScrollPicker.setIsCirculation(true); stringScrollPicker.setCanTap(true); stringScrollPicker.setDisallowInterceptTouch(true); LayoutParams stringScrollPicker_Params = new LayoutParams(LayoutParams.MATCH_PARENT,Axis.scaleX(150)); Auto_layout.addView(stringScrollPicker,stringScrollPicker_Params); stringScrollPicker.setData(newList); stringScrollPicker.setOnSelectedListener(new ScrollPickerView.OnSelectedListener() {  @Override  public void onSelected(ScrollPickerView scrollPickerView, final int position) {  mPosition = position;  handler.postDelayed(delayRun, 1500);  } }); stringScrollPicker.setOnSelectedListener(new StringScrollPicker.OnDataSelectedListener() {  @Override  public void DataSelected(CharSequence data) {  //tv.setText("电池剩余"+data+"%提醒你");  } }); stringScrollPicker.setSelectedPosition(0,false);//中间Item位置 stringScrollPicker.setVisibility(INVISIBLE); stringScrollPicker.setOnTouchListener(new OnTouchListener() {  @Override  public boolean onTouch(View v, MotionEvent event) {  switch (event.getAction()){   case MotionEvent.ACTION_DOWN:   img.setBackgroundResource(R.drawable.battery_btn_p);   if(delayRun!=null){    handler.removeCallbacks(delayRun);   }   break;  }  return false;  } }); img.setOnClickListener(new OnClickListener() {  @Override  public void onClick(View v) {  stringScrollPicker.setVisibility(VISIBLE);  tv_middle.setVisibility(INVISIBLE);  img_right.setVisibility(INVISIBLE);  img_left.setVisibility(INVISIBLE);  img.setBackgroundResource(R.drawable.battery_btn_p);  } }); } /** * 风速设置 * @param mPosition */ public void setAirTemperature(int mPosition){ /**  * 在设置的时候不刷新  */ if(stringScrollPicker.getVisibility() == INVISIBLE){  if(mPosition > 32){  mPosition = 32;  }  stringScrollPicker.setSelectedPosition(mPosition-18,false);  tv_middle.setText(newList.get(mPosition-18)); } } public TemperatureListener mListener; public void setOnTemperatureListener (TemperatureListener listener) { mListener = listener; } public interface TemperatureListener { void setAirTemper(int temperature); }}

StringScrollPicker 类

package com.demo.ui.view;import android.annotation.TargetApi;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.os.Build;import android.support.annotation.RequiresApi;import android.text.Layout;import android.text.StaticLayout;import android.text.TextPaint;import android.util.AttributeSet;import android.util.Log;import com.demo.factory.Axis;import com.demo.utils.ColorUtil;import java.util.ArrayList;import java.util.Arrays;import java.util.List;public class StringScrollPicker extends ScrollPickerView<CharSequence> { private int mMeasureWidth; private int mMeasureHeight; private TextPaint mPaint; // private int mMinTextSize = Axis.scaleX(64); // 最小的字体 private int mMaxTextSize = Axis.scaleX(64); // 最大的字体 // 字体渐变颜色 private int mStartColor = Color.WHITE; // 中间选中item的颜色 private int mEndColor = Color.GRAY; // 上下两边的颜色 private int mMaxLineWidth = -1; // 最大的行宽,默认为itemWidth.超过后文字自动换行 private Layout.Alignment mAlignment = Layout.Alignment.ALIGN_CENTER; // 对齐方式,默认居中 @TargetApi(Build.VERSION_CODES.CUPCAKE) public StringScrollPicker(Context context) { this(context, null); } @RequiresApi(api = Build.VERSION_CODES.CUPCAKE) public StringScrollPicker(Context context, AttributeSet attrs) { this(context, attrs, 0); } @RequiresApi(api = Build.VERSION_CODES.CUPCAKE) public StringScrollPicker(Context context, AttributeSet attrs,    int defStyleAttr) { super(context, attrs, defStyleAttr); mPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); mPaint.setStyle(Paint.Style.FILL); mPaint.setColor(Color.BLACK); setData(new ArrayList<CharSequence>(Arrays.asList(new String[]{  "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve" }))); } /** * @param startColor 正中间的颜色 * @param endColor 上下两边的颜色 */ public void setColor(int startColor, int endColor) { mStartColor = startColor; mEndColor = endColor; invalidate(); } /** * item文字大小 * * @param minText 沒有被选中时的最小文字 * @param maxText 被选中时的最大文字 */ public void setTextSize(int minText, int maxText) { mMinTextSize = minText; mMaxTextSize = maxText; invalidate(); } public int getStartColor() { return mStartColor; } public int getEndColor() { return mEndColor; } public int getMinTextSize() { return mMinTextSize; } public int getMaxTextSize() { return mMaxTextSize; } public int getMaxLineWidth() { return mMaxLineWidth; } /** * 最大的行宽,默认为itemWidth.超过后文字自动换行 * @param maxLineWidth */ public void setMaxLineWidth(int maxLineWidth) { mMaxLineWidth = maxLineWidth; } /** * 最大的行宽,默认为itemWidth.超过后文字自动换行 * @return */ public Layout.Alignment getAlignment() { return mAlignment; } public void setAlignment(Layout.Alignment alignment) { mAlignment = alignment; } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mMeasureWidth = getMeasuredWidth(); mMeasureHeight = getMeasuredHeight(); if (mMaxLineWidth < 0) {  mMaxLineWidth = getItemWidth(); } } @Override public void drawItem(Canvas canvas, List<CharSequence> data, int position, int relative, float moveLength, float top) { CharSequence text = data.get(position); int itemSize = getItemSize(); // 设置文字大小 if (relative == -1) { // 上一个  if (moveLength < 0) { // 向上滑动  mPaint.setTextSize(mMinTextSize);  } else { // 向下滑动  mPaint.setTextSize(mMinTextSize + (mMaxTextSize - mMinTextSize)   * moveLength / itemSize);  } } else if (relative == 0) { // 中间item,当前选中  mPaint.setTextSize(mMinTextSize + (mMaxTextSize - mMinTextSize)   * (itemSize - Math.abs(moveLength)) / itemSize); } else if (relative == 1) { // 下一个  if (moveLength > 0) { // 向下滑动  mPaint.setTextSize(mMinTextSize);  } else { // 向上滑动  mPaint.setTextSize(mMinTextSize + (mMaxTextSize - mMinTextSize)   * -moveLength / itemSize);  } } else { // 其他  mPaint.setTextSize(mMinTextSize); } StaticLayout layout = new StaticLayout(text, 0, text.length(), mPaint, mMaxLineWidth, mAlignment, 1.0F, 0.0F, true, null, 0); float x = 0; float y = 0; float lineWidth = layout.getWidth(); if (isHorizontal()) { // 水平滚动  x = top + (getItemWidth() - lineWidth) / 2;  y = (getItemHeight() - layout.getHeight()) / 2; } else { // 垂直滚动  x = (getItemWidth() - lineWidth) / 2;  y = top + (getItemHeight() - layout.getHeight()) / 2; } // 计算渐变颜色 computeColor(relative, itemSize, moveLength,text);// canvas.drawText(text, x, y, mPaint); canvas.save(); canvas.translate(x, y); layout.draw(canvas); canvas.restore(); } /** * 计算字体颜色,渐变 * * @param relative  相对中间item的位置 */ private String lastString; private String nowSring; private void computeColor(int relative, int itemSize, float moveLength, CharSequence text) { int color = mEndColor; //  其他默认为mEndColor if (relative == -1 || relative == 1) { // 上一个或下一个  // 处理上一个item且向上滑动 或者 处理下一个item且向下滑动 ,颜色为mEndColor  if ((relative == -1 && moveLength < 0)   || (relative == 1 && moveLength > 0)) {  color = mEndColor;  } else { // 计算渐变的颜色  float rate = (itemSize - Math.abs(moveLength))   / itemSize;  color = ColorUtil.computeGradientColor(mStartColor, mEndColor, rate);  } } else if (relative == 0) { // 中间item  float rate = Math.abs(moveLength) / itemSize;  color = ColorUtil.computeGradientColor(mStartColor, mEndColor, rate);  nowSring = text.toString();  if(nowSring != lastString){  Log.e("text=====",text+"");  if(mListener != null){   mListener.DataSelected(text);  }  }  lastString = nowSring; } mPaint.setColor(color); } public interface OnDataSelectedListener { void DataSelected(CharSequence data); } public void setOnSelectedListener(OnDataSelectedListener listener) { mListener = listener; } public OnDataSelectedListener mListener;}

ScrollPickerView 类

package com.demo.ui.view;import android.animation.Animator;import android.animation.AnimatorListenerAdapter;import android.animation.ValueAnimator;import android.annotation.TargetApi;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.drawable.ColorDrawable;import android.graphics.drawable.Drawable;import android.os.Build;import android.support.annotation.RequiresApi;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.View;import android.view.ViewParent;import android.view.animation.Interpolator;import android.widget.Scroller;import com.demo.R;import com.demo.utils.LogUtils;import java.util.ArrayList;import java.util.List;/** * 滚动选择器,带惯性滑动 */public abstract class ScrollPickerView<T> extends View { private int mVisibleItemCount = 3; // 可见的item数量 private boolean mIsInertiaScroll = true; // 快速滑动时是否惯性滚动一段距离,默认开启 private boolean mIsCirculation = true; // 是否循环滚动,默认开启 /* 不允许父组件拦截触摸事件,设置为true为不允许拦截,此时该设置才生效 当嵌入到ScrollView等滚动组件中,为了使该自定义滚动选择器可以正常工作,请设置为true */ private boolean mDisallowInterceptTouch = false; private int mSelected; // 当前选中的item下标 private int mLastSelected; // 当前选中的item下标 private List<T> mData; private int mItemHeight = 0; // 每个条目的高度,当垂直滚动时,高度=mMeasureHeight/mVisibleItemCount private int mItemWidth = 0; // 每个条目的宽度,当水平滚动时,宽度=mMeasureWidth/mVisibleItemCount private int mItemSize; // 当垂直滚动时,mItemSize = mItemHeight;水平滚动时,mItemSize = mItemWidth private int mCenterPosition = -1; // 中间item的位置,0<=mCenterPosition<mVisibleItemCount,默认为 mVisibleItemCount / 2 private int mCenterY; // 中间item的起始坐标y(不考虑偏移),当垂直滚动时,y= mCenterPosition*mItemHeight private int mCenterX; // 中间item的起始坐标x(不考虑偏移),当垂直滚动时,x = mCenterPosition*mItemWidth private int mCenterPoint; // 当垂直滚动时,mCenterPoint = mCenterY;水平滚动时,mCenterPoint = mCenterX private float mLastMoveY; // 触摸的坐标y private float mLastMoveX; // 触摸的坐标X private float mMoveLength = 0; // item移动长度,负数表示向上移动,正数表示向下移动 private GestureDetector mGestureDetector; private OnSelectedListener mListener; private Scroller mScroller; private boolean mIsFling; // 是否正在惯性滑动 private boolean mIsMovingCenter; // 是否正在滑向中间 // 可以把scroller看做模拟的触屏滑动操作,mLastScrollY为上次触屏滑动的坐标 private int mLastScrollY = 0; // Scroller的坐标y private int mLastScrollX = 0; // Scroller的坐标x private boolean mDisallowTouch = false; // 不允许触摸 private Paint mPaint; // private Drawable mCenterItemBackground = null; // 中间选中item的背景色 private boolean mCanTap = true; // 单击切换选项或触发点击监听器 private boolean mIsHorizontal = false; // 是否水平滚动 private boolean mDrawAllItem = false; // 是否绘制每个item(包括在边界外的item) @RequiresApi(api = Build.VERSION_CODES.CUPCAKE) public ScrollPickerView(Context context, AttributeSet attrs) { this(context, attrs, 0); } @TargetApi(Build.VERSION_CODES.HONEYCOMB) @RequiresApi(api = Build.VERSION_CODES.CUPCAKE) public ScrollPickerView(Context context, AttributeSet attrs,    int defStyleAttr) { super(context, attrs, defStyleAttr); mGestureDetector = new GestureDetector(getContext(),  new FlingOnGestureListener()); mScroller = new Scroller(getContext()); mAutoScrollAnimator = ValueAnimator.ofInt(0, 0); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setStyle(Paint.Style.FILL); init(attrs); } private void init(AttributeSet attrs) { if (attrs != null) {  TypedArray typedArray = getContext().obtainStyledAttributes(attrs,   R.styleable.ScrollPickerView);  if (typedArray.hasValue(R.styleable.ScrollPickerView_spv_center_item_background)) {  setCenterItemBackground(typedArray.getDrawable(R.styleable.ScrollPickerView_spv_center_item_background));  }  setVisibleItemCount(typedArray.getInt(   R.styleable.ScrollPickerView_spv_visible_item_count,   getVisibleItemCount()));  setCenterPosition(typedArray.getInt(   R.styleable.ScrollPickerView_spv_center_item_position,   getCenterPosition()));  setIsCirculation(typedArray.getBoolean(R.styleable.ScrollPickerView_spv_is_circulation, isIsCirculation()));  setDisallowInterceptTouch(typedArray.getBoolean(R.styleable.ScrollPickerView_spv_disallow_intercept_touch, isDisallowInterceptTouch()));  setHorizontal(typedArray.getInt(R.styleable.ScrollPickerView_spv_orientation, mIsHorizontal ? 1 : 2) == 1);  typedArray.recycle(); } } @Override protected void onDraw(Canvas canvas) { if (mData == null || mData.size() <= 0) {  return; } // 选中item的背景色 if (mCenterItemBackground != null) {  mCenterItemBackground.draw(canvas); } // 只绘制可见的item int length = Math.max(mCenterPosition + 1, mVisibleItemCount - mCenterPosition); int position; int start = Math.min(length, mData.size()); if (mDrawAllItem) {  start = mData.size(); } // 上下两边 for (int i = start; i >= 1; i--) { // 先从远离中间位置的item绘制,当item内容偏大时,较近的item覆盖在较远的上面  if (mDrawAllItem || i <= mCenterPosition + 1) { // 上面的items,相对位置为 -i  position = mSelected - i < 0 ? mData.size() + mSelected - i   : mSelected - i;  // 传入位置信息,绘制item  if (mIsCirculation) {   drawItem(canvas, mData, position, -i, mMoveLength, mCenterPoint + mMoveLength - i * mItemSize);  } else if (mSelected - i >= 0) { // 非循环滚动   drawItem(canvas, mData, position, -i, mMoveLength, mCenterPoint + mMoveLength - i * mItemSize);  }  }  if (mDrawAllItem || i <= mVisibleItemCount - mCenterPosition) { // 下面的items,相对位置为 i  position = mSelected + i >= mData.size() ? mSelected + i   - mData.size() : mSelected + i;  // 传入位置信息,绘制item  if (mIsCirculation) {   drawItem(canvas, mData, position, i, mMoveLength, mCenterPoint + mMoveLength + i * mItemSize);  } else if (mSelected + i < mData.size()) { // 非循环滚动   drawItem(canvas, mData, position, i, mMoveLength, mCenterPoint + mMoveLength + i * mItemSize);  }  } } // 选中的item drawItem(canvas, mData, mSelected, 0, mMoveLength, mCenterPoint + mMoveLength); } /** * 绘制item * * @param canvas * @param data  数据集 * @param position 在data数据集中的位置 * @param relative 相对中间item的位置,relative==0表示中间item,relative<0表示上(左)边的item,relative>0表示下(右)边的item * @param moveLength 中间item滚动的距离,moveLength<0则表示向上(右)滚动的距离,moveLength>0则表示向下(左)滚动的距离 * @param top 当前绘制item的坐标,当垂直滚动时为顶部y的坐标;当水平滚动时为item最左边x的坐标 */ public abstract void drawItem(Canvas canvas, List<T> data, int position, int relative, float moveLength, float top); @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); reset(); } private void reset() { if (mCenterPosition < 0) {  mCenterPosition = mVisibleItemCount / 2; } if (mIsHorizontal) {  mItemHeight = getMeasuredHeight();  mItemWidth = getMeasuredWidth() / mVisibleItemCount;  mCenterY = 0;  mCenterX = mCenterPosition * mItemWidth;  mItemSize = mItemWidth;  mCenterPoint = mCenterX; } else {  mItemHeight = getMeasuredHeight() / mVisibleItemCount;  mItemWidth = getMeasuredWidth();  mCenterY = mCenterPosition * mItemHeight;  mCenterX = 0;  mItemSize = mItemHeight;  mCenterPoint = mCenterY; } if (mCenterItemBackground != null) {  mCenterItemBackground.setBounds(mCenterX, mCenterY, mCenterX + mItemWidth, mCenterY + mItemHeight); } } @RequiresApi(api = Build.VERSION_CODES.FROYO) @Override public boolean onTouchEvent(MotionEvent event) { if (mDisallowTouch) { // 不允许触摸  return true; } if (mGestureDetector.onTouchEvent(event)) {  return true; } switch (event.getActionMasked()) {  case MotionEvent.ACTION_MOVE:  if (mIsHorizontal) {   if (Math.abs(event.getX() - mLastMoveX) < 0.1f) {   return true;   }   mMoveLength += event.getX() - mLastMoveX;  } else {   if (Math.abs(event.getY() - mLastMoveY) < 0.1f) {   return true;   }   mMoveLength += event.getY() - mLastMoveY;  }  mLastMoveY = event.getY();  mLastMoveX = event.getX();  checkCirculation();  invalidate();  break;  case MotionEvent.ACTION_UP:  mLastMoveY = event.getY();  mLastMoveX = event.getX();  moveToCenter();  break; } return true; } /** * @param curr * @param end */ private void computeScroll(int curr, int end, float rate) { if (rate < 1) { // 正在滚动  if (mIsHorizontal) {  // 可以把scroller看做模拟的触屏滑动操作,mLastScrollX为上次滑动的坐标  mMoveLength = mMoveLength + curr - mLastScrollX;  mLastScrollX = curr;  } else {  // 可以把scroller看做模拟的触屏滑动操作,mLastScrollY为上次滑动的坐标  mMoveLength = mMoveLength + curr - mLastScrollY;  mLastScrollY = curr;  }  checkCirculation();  invalidate(); } else { // 滚动完毕  mIsMovingCenter = false;  mLastScrollY = 0;  mLastScrollX = 0;  // 直接居中,不通过动画  if (mMoveLength > 0) { //// 向下滑动  if (mMoveLength < mItemSize / 2) {   mMoveLength = 0;  } else {   mMoveLength = mItemSize;  }  } else {  if (-mMoveLength < mItemSize / 2) {   mMoveLength = 0;  } else {   mMoveLength = -mItemSize;  }  }  checkCirculation();  mMoveLength = 0;  mLastScrollY = 0;  mLastScrollX = 0;  notifySelected(true);  invalidate(); } } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { // 正在滚动  if (mIsHorizontal) {  // 可以把scroller看做模拟的触屏滑动操作,mLastScrollX为上次滑动的坐标  mMoveLength = mMoveLength + mScroller.getCurrX() - mLastScrollX;  } else {  // 可以把scroller看做模拟的触屏滑动操作,mLastScrollY为上次滑动的坐标  mMoveLength = mMoveLength + mScroller.getCurrY() - mLastScrollY;  }  mLastScrollY = mScroller.getCurrY();  mLastScrollX = mScroller.getCurrX();  checkCirculation(); // 检测当前选中的item  invalidate(); } else { // 滚动完毕  if (mIsFling) {  mIsFling = false;  moveToCenter(); // 滚动到中间位置  } else if (mIsMovingCenter) { // 选择完成,回调给监听器  mMoveLength = 0;  mIsMovingCenter = false;  mLastScrollY = 0;  mLastScrollX = 0;  notifySelected(true);  } } } public void cancelScroll() { mLastScrollY = 0; mLastScrollX = 0; mIsFling = mIsMovingCenter = false; mScroller.abortAnimation(); stopAutoScroll(); } // 检测当前选择的item位置 private void checkCirculation() { if (mMoveLength >= mItemSize) { // 向下滑动  // 该次滚动距离中越过的item数量  int span = (int) (mMoveLength / mItemSize);  mSelected -= span;  if (mSelected < 0) { // 滚动顶部,判断是否循环滚动  if (mIsCirculation) {   do {   mSelected = mData.size() + mSelected;   } while (mSelected < 0); // 当越过的item数量超过一圈时   mMoveLength = (mMoveLength - mItemSize) % mItemSize;  } else { // 非循环滚动   mSelected = 0;   mMoveLength = mItemSize;   if (mIsFling) { // 停止惯性滑动,根据computeScroll()中的逻辑,下一步将调用moveToCenter()   mScroller.forceFinished(true);   }   if (mIsMovingCenter) { // 移回中间位置   scroll(mMoveLength, 0);   }  }  } else {  mMoveLength = (mMoveLength - mItemSize) % mItemSize;  } } else if (mMoveLength <= -mItemSize) { // 向上滑动  // 该次滚动距离中越过的item数量  int span = (int) (-mMoveLength / mItemSize);  mSelected += span;  if (mSelected >= mData.size()) { // 滚动末尾,判断是否循环滚动  if (mIsCirculation) {   do {   mSelected = mSelected - mData.size();   } while (mSelected >= mData.size()); // 当越过的item数量超过一圈时   mMoveLength = (mMoveLength + mItemSize) % mItemSize;  } else { // 非循环滚动   mSelected = mData.size() - 1;   mMoveLength = -mItemSize;   if (mIsFling) { // 停止惯性滑动,根据computeScroll()中的逻辑,下一步将调用moveToCenter()   mScroller.forceFinished(true);   }   if (mIsMovingCenter) { // 移回中间位置   scroll(mMoveLength, 0);   }  }  } else {  mMoveLength = (mMoveLength + mItemSize) % mItemSize;  } } } // 移动到中间位置 private void moveToCenter() { if (!mScroller.isFinished() || mIsFling || mMoveLength == 0) {  return; } cancelScroll(); // 向下滑动 if (mMoveLength > 0) {  if (mIsHorizontal) {  if (mMoveLength < mItemWidth / 2) {   scroll(mMoveLength, 0);  } else {   scroll(mMoveLength, mItemWidth);  }  } else {  if (mMoveLength < mItemHeight / 2) {   scroll(mMoveLength, 0);  } else {   scroll(mMoveLength, mItemHeight);  }  } } else {  if (mIsHorizontal) {  if (-mMoveLength < mItemWidth / 2) {   scroll(mMoveLength, 0);  } else {   scroll(mMoveLength, -mItemWidth);  }  } else {  if (-mMoveLength < mItemHeight / 2) {   scroll(mMoveLength, 0);  } else {   scroll(mMoveLength, -mItemHeight);  }  } } } // 平滑滚动 private void scroll(float from, int to) { if (mIsHorizontal) {  mLastScrollX = (int) from;  mIsMovingCenter = true;  mScroller.startScroll((int) from, 0, 0, 0);  mScroller.setFinalX(to); } else {  mLastScrollY = (int) from;  mIsMovingCenter = true;  mScroller.startScroll(0, (int) from, 0, 0);  mScroller.setFinalY(to); } invalidate(); } // 惯性滑动, private void fling(float from, float vel) { if (mIsHorizontal) {  mLastScrollX = (int) from;  mIsFling = true;  // 最多可以惯性滑动10个item  mScroller.fling((int) from, 0, (int) vel, 0, -10 * mItemWidth,   10 * mItemWidth, 0, 0); } else {  mLastScrollY = (int) from;  mIsFling = true;  // 最多可以惯性滑动10个item  mScroller.fling(0, (int) from, 0, (int) vel, 0, 0, -10 * mItemHeight,   10 * mItemHeight); } invalidate(); } private void notifySelected(final boolean trigger) { if (mListener != null) {  // 告诉监听器选择完毕  post(new Runnable() {  @Override  public void run() {   if(mLastSelected != mSelected){   if(trigger){    mListener.onSelected(ScrollPickerView.this, mSelected);   }   }   mLastSelected = mSelected;  }  }); } } private boolean mIsAutoScrolling = false; private ValueAnimator mAutoScrollAnimator; private final static SlotInterpolator sAutoScrollInterpolator = new SlotInterpolator(); /** * 自动滚动(必须设置为可循环滚动) * * @param position * @param duration * @param speed 每毫秒移动的像素点 */ @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB) public void autoScrollFast(final int position, long duration, float speed, final Interpolator interpolator) { if (mIsAutoScrolling || !mIsCirculation) {  return; } cancelScroll(); mIsAutoScrolling = true; int length = (int) (speed * duration); int circle = (int) (length * 1f / (mData.size() * mItemSize) + 0.5f); // 圈数 circle = circle <= 0 ? 1 : circle; int aPlan = circle * (mData.size()) * mItemSize + (mSelected - position) * mItemSize; int bPlan = aPlan + (mData.size()) * mItemSize; // 多一圈 // 让其尽量接近length final int end = Math.abs(length - aPlan) < Math.abs(length - bPlan) ? aPlan : bPlan; mAutoScrollAnimator.cancel(); mAutoScrollAnimator.setIntValues(0, end); mAutoScrollAnimator.setInterpolator(interpolator); mAutoScrollAnimator.setDuration(duration); mAutoScrollAnimator.removeAllUpdateListeners(); if (end != 0) { // itemHeight为0导致endy=0  mAutoScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  @Override  public void onAnimationUpdate(ValueAnimator animation) {   float rate = 0;   rate = animation.getCurrentPlayTime() * 1f / animation.getDuration();   computeScroll((int) animation.getAnimatedValue(), end, rate);  }  });  mAutoScrollAnimator.removeAllListeners();  mAutoScrollAnimator.addListener(new AnimatorListenerAdapter() {  @Override  public void onAnimationEnd(Animator animation) {   super.onAnimationEnd(animation);   mIsAutoScrolling = false;  }  });  mAutoScrollAnimator.start(); } else {  computeScroll(end, end, 1);  mIsAutoScrolling = false; } } /** * 自动滚动,默认速度为 0.6dp/ms * * @see ScrollPickerView#autoScrollFast(int, long, float, Interpolator) */ @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB) public void autoScrollFast(final int position, long duration) { float speed = dip2px(0.6f); autoScrollFast(position, duration, speed, sAutoScrollInterpolator); } /** * 自动滚动 * * @see ScrollPickerView#autoScrollFast(int, long, float, Interpolator) */ @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB) public void autoScrollFast(final int position, long duration, float speed) { autoScrollFast(position, duration, speed, sAutoScrollInterpolator); } /** * 滚动到指定位置 * * @param toPosition  需要滚动到的位置 * @param duration  滚动时间 * @param interpolator */ @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB) public void autoScrollToPosition(int toPosition, long duration, final Interpolator interpolator) { toPosition = toPosition % mData.size(); final int endY = (mSelected - toPosition) * mItemHeight; autoScrollTo(endY, duration, interpolator, false); } /** * @param endY   需要滚动到的位置 * @param duration  滚动时间 * @param interpolator * @param canIntercept 能否终止滚动,比如触摸屏幕终止滚动 */ @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB) public void autoScrollTo(final int endY, long duration, final Interpolator interpolator, boolean canIntercept) { if (mIsAutoScrolling) {  return; } final boolean temp = mDisallowTouch; mDisallowTouch = !canIntercept; mIsAutoScrolling = true; mAutoScrollAnimator.cancel(); mAutoScrollAnimator.setIntValues(0, endY); mAutoScrollAnimator.setInterpolator(interpolator); mAutoScrollAnimator.setDuration(duration); mAutoScrollAnimator.removeAllUpdateListeners(); mAutoScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  @Override  public void onAnimationUpdate(ValueAnimator animation) {  float rate = 0;  rate = animation.getCurrentPlayTime() * 1f / animation.getDuration();  computeScroll((int) animation.getAnimatedValue(), endY, rate);  } }); mAutoScrollAnimator.removeAllListeners(); mAutoScrollAnimator.addListener(new AnimatorListenerAdapter() {  @Override  public void onAnimationEnd(Animator animation) {  super.onAnimationEnd(animation);  mIsAutoScrolling = false;  mDisallowTouch = temp;  } }); mAutoScrollAnimator.start(); } /** * 停止自动滚动 */ @TargetApi(Build.VERSION_CODES.HONEYCOMB) public void stopAutoScroll() { mIsAutoScrolling = false; mAutoScrollAnimator.cancel(); } private static class SlotInterpolator implements Interpolator { @Override public float getInterpolation(float input) {  return (float) (Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; } } /** * 快速滑动时,惯性滑动一段距离 * * @author huangziwei */ private class FlingOnGestureListener extends GestureDetector.SimpleOnGestureListener { private boolean mIsScrollingLastTime = false; public boolean onDown(MotionEvent e) {  if (mDisallowInterceptTouch) { // 不允许父组件拦截事件  ViewParent parent = getParent();  if (parent != null) {   parent.requestDisallowInterceptTouchEvent(true);  }  }  mIsScrollingLastTime = isScrolling(); // 记录是否从滚动状态终止  // 点击时取消所有滚动效果  cancelScroll();  mLastMoveY = e.getY();  mLastMoveX = e.getX();  return true; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,    final float velocityY) {  // 惯性滑动  if (mIsInertiaScroll) {  cancelScroll();  if (mIsHorizontal) {   fling(mMoveLength, velocityX);  } else {   fling(mMoveLength, velocityY);  }  }  return true; } @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB) @Override public boolean onSingleTapUp(MotionEvent e) {  mLastMoveY = e.getY();  mLastMoveX = e.getX();  float lastMove = 0;  if (isHorizontal()) {  mCenterPoint = mCenterX;  lastMove = mLastMoveX;  LogUtils.e("lastMove===",lastMove+"");  LogUtils.e("mCenterPoint===",mCenterPoint+"");  } else {  mCenterPoint = mCenterY;  lastMove = mLastMoveY;  }  if (mCanTap && !isScrolling() && !mIsScrollingLastTime) {  if (lastMove >= mCenterPoint && lastMove <= mCenterPoint + mItemSize) {   //performClick();  } else if (lastMove < mCenterPoint) {   int bs = (int)((mCenterPoint+mItemSize) - lastMove)/mItemSize;   int move = bs*mItemSize;   autoScrollTo(move, 150, sAutoScrollInterpolator, false);  } else if (lastMove > mCenterPoint + mItemSize) {   int bs = (int)((lastMove -mCenterPoint)/mItemWidth);   int move = -bs*mItemSize;   autoScrollTo(move, 150, sAutoScrollInterpolator, false);  } else {   moveToCenter();  }  } else {  moveToCenter();  }  return true; } } public List<T> getData() { return mData; } public void setData(List<T> data) { if (data == null) {  mData = new ArrayList<T>(); } else {  this.mData = data; } mSelected = mData.size() / 2; invalidate(); } public T getSelectedItem() { return mData.get(mSelected); } public int getSelectedPosition() { return mSelected; } public void setSelectedPosition(int position,boolean trigger) { if (position < 0 || position > mData.size() - 1  || position == mSelected) {  return; } mSelected = position; invalidate(); if (mListener != null) {  notifySelected(trigger); } } public void setOnSelectedListener(OnSelectedListener listener) { mListener = listener; } public OnSelectedListener getListener() { return mListener; } public boolean isInertiaScroll() { return mIsInertiaScroll; } public void setInertiaScroll(boolean inertiaScroll) { this.mIsInertiaScroll = inertiaScroll; } public boolean isIsCirculation() { return mIsCirculation; } public void setIsCirculation(boolean isCirculation) { this.mIsCirculation = false; } public boolean isDisallowInterceptTouch() { return mDisallowInterceptTouch; } public int getVisibleItemCount() { return mVisibleItemCount; } public void setVisibleItemCount(int visibleItemCount) { mVisibleItemCount = visibleItemCount; reset(); invalidate(); } /** * 是否允许父元素拦截事件,设置true后可以保证在ScrollView下正常滚动 */ public void setDisallowInterceptTouch(boolean disallowInterceptTouch) { mDisallowInterceptTouch = disallowInterceptTouch; } public int getItemHeight() { return mItemHeight; } public int getItemWidth() { return mItemWidth; } /** * @return 当垂直滚动时,mItemSize = mItemHeight;水平滚动时,mItemSize = mItemWidth */ public int getItemSize() { return mItemSize; } /** * @return 中间item的起始坐标x(不考虑偏移), 当垂直滚动时,x = mCenterPosition*mItemWidth */ public int getCenterX() { return mCenterX; } /** * @return 中间item的起始坐标y(不考虑偏移), 当垂直滚动时,y= mCenterPosition*mItemHeight */ public int getCenterY() { return mCenterY; } /** * @return 当垂直滚动时,mCenterPoint = mCenterY;水平滚动时,mCenterPoint = mCenterX */ public int getCenterPoint() { return mCenterPoint; } public boolean isDisallowTouch() { return mDisallowTouch; } /** * 设置是否允许手动触摸滚动 * * @param disallowTouch */ public void setDisallowTouch(boolean disallowTouch) { mDisallowTouch = disallowTouch; } /** * 中间item的位置,0 <= centerPosition <= mVisibleItemCount * * @param centerPosition */ public void setCenterPosition(int centerPosition) { if (centerPosition < 0) {  mCenterPosition = 0; } else if (centerPosition >= mVisibleItemCount) {  mCenterPosition = mVisibleItemCount - 1; } else {  mCenterPosition = centerPosition; } mCenterY = mCenterPosition * mItemHeight; invalidate(); } /** * 中间item的位置,默认为 mVisibleItemCount / 2 * * @return */ public int getCenterPosition() { return mCenterPosition; } public void setCenterItemBackground(Drawable centerItemBackground) { mCenterItemBackground = centerItemBackground; mCenterItemBackground.setBounds(mCenterX, mCenterY, mCenterX + mItemWidth, mCenterY + mItemHeight); invalidate(); } public void setCenterItemBackground(int centerItemBackgroundColor) { mCenterItemBackground = new ColorDrawable(centerItemBackgroundColor); mCenterItemBackground.setBounds(mCenterX, mCenterY, mCenterX + mItemWidth, mCenterY + mItemHeight); invalidate(); } public Drawable getCenterItemBackground() { return mCenterItemBackground; } public boolean isScrolling() { return mIsFling || mIsMovingCenter || mIsAutoScrolling; } public boolean isFling() { return mIsFling; } public boolean isMovingCenter() { return mIsMovingCenter; } public boolean isAutoScrolling() { return mIsAutoScrolling; } public boolean isCanTap() { return mCanTap; } /** * 设置 单击切换选项或触发点击监听器 * * @param canTap */ public void setCanTap(boolean canTap) { mCanTap = canTap; } public boolean isHorizontal() { return mIsHorizontal; } public boolean isVertical() { return !mIsHorizontal; } public void setHorizontal(boolean horizontal) { if (mIsHorizontal == horizontal) {  return; } mIsHorizontal = horizontal; reset(); if (mIsHorizontal) {  mItemSize = mItemWidth; } else {  mItemSize = mItemHeight; } invalidate(); } public void setVertical(boolean vertical) { if (mIsHorizontal == !vertical) {  return; } mIsHorizontal = !vertical; reset(); if (mIsHorizontal) {  mItemSize = mItemWidth; } else {  mItemSize = mItemHeight; } invalidate(); } public boolean isDrawAllItem() { return mDrawAllItem; } public void setDrawAllItem(boolean drawAllItem) { mDrawAllItem = drawAllItem; } /** * @author huangziwei */ public interface OnSelectedListener { void onSelected(ScrollPickerView scrollPickerView, int position); } public int dip2px(float dipVlue) { DisplayMetrics metrics = getContext().getResources().getDisplayMetrics(); float sDensity = metrics.density; return (int) (dipVlue * sDensity + 0.5F); } @Override public void setVisibility(int visibility) { super.setVisibility(visibility); if (visibility == VISIBLE) {  moveToCenter(); } }}

ColorUtil 类

package com.demo.utils;import android.graphics.Color;/** * 颜色工具栏 */public class ColorUtil { /** * 计算渐变后的颜色 * * @param startColor 开始颜色 * @param endColor 结束颜色 * @param rate 渐变率(0,1) * @return 渐变后的颜色,当rate=0时,返回startColor,当rate=1时返回endColor */ public static int computeGradientColor(int startColor, int endColor, float rate) { if (rate < 0) {  rate = 0; } if (rate > 1) {  rate = 1; } int alpha = Color.alpha(endColor) - Color.alpha(startColor); int red = Color.red(endColor) - Color.red(startColor); int green = Color.green(endColor) - Color.green(startColor); int blue = Color.blue(endColor) - Color.blue(startColor); return Color.argb(  Math.round(Color.alpha(startColor) + alpha * rate),  Math.round(Color.red(startColor) + red * rate),  Math.round(Color.green(startColor) + green * rate),  Math.round(Color.blue(startColor) + blue * rate)); }}

调用

/** * 温度*/airTemperatureView = new AirTemperatureView(context); LinearLayout.LayoutParams airTemperatureView_Params = new LinearLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,Axis.scaleX(230)); airTemperatureView_Params.setMargins(0,Axis.scaleX(100),0,0); bodyLayout.addView(airTemperatureView,airTemperatureView_Params);//父布局 addView() airTemperatureView.setOnTemperatureListener(new AirTemperatureView.TemperatureListener() { @Override public void setAirTemper(int temperature) { LogUtils.e("空调温度===",temperature+""); setTemperature(temperature);//网络请求方法 }});

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VEVB武林网。


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表