国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > 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開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 铜川市| 历史| 谷城县| 黎城县| 四平市| 湖州市| 西华县| 临湘市| 长泰县| 酒泉市| 嘉善县| 崇礼县| 醴陵市| 德令哈市| 象州县| 柯坪县| 札达县| 屏东市| 花莲县| 铜梁县| 临邑县| 宁夏| 邯郸县| 平乡县| 大名县| 洛宁县| 马鞍山市| 象州县| 皋兰县| 商丘市| 抚松县| 从江县| 逊克县| 临高县| 中牟县| 金沙县| 德江县| 东乌珠穆沁旗| 陆河县| 巴青县| 武城县|