Android自定義控件實(shí)現(xiàn)按鈕滾動(dòng)選擇效果
本文實(shí)例為大家分享了Android實(shí)現(xiàn)按鈕滾動(dòng)選擇效果的具體代碼,供大家參考,具體內(nèi)容如下
效果圖
代碼實(shí)現(xiàn)
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(); /** * 延遲線程,看是否還有下一個(gè)字符輸入 */ 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("空調(diào)刷新===","溫度"); } }; 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); /** * 滑動(dòng)選擇器 */ 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個(gè) 第3個(gè) (3-1)個(gè)位中間 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); } }); } /** * 風(fēng)速設(shè)置 * @param mPosition */ public void setAirTemperature(int mPosition){ /** * 在設(shè)置的時(shí)候不刷新 */ 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; // 最大的行寬,默認(rèn)為itemWidth.超過后文字自動(dòng)換行 private Layout.Alignment mAlignment = Layout.Alignment.ALIGN_CENTER; // 對(duì)齊方式,默認(rèn)居中 @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 沒有被選中時(shí)的最小文字 * @param maxText 被選中時(shí)的最大文字 */ 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; } /** * 最大的行寬,默認(rèn)為itemWidth.超過后文字自動(dòng)換行 * @param maxLineWidth */ public void setMaxLineWidth(int maxLineWidth) { mMaxLineWidth = maxLineWidth; } /** * 最大的行寬,默認(rèn)為itemWidth.超過后文字自動(dòng)換行 * @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(); // 設(shè)置文字大小 if (relative == -1) { // 上一個(gè) if (moveLength < 0) { // 向上滑動(dòng) mPaint.setTextSize(mMinTextSize); } else { // 向下滑動(dòng) mPaint.setTextSize(mMinTextSize + (mMaxTextSize - mMinTextSize) * moveLength / itemSize); } } else if (relative == 0) { // 中間item,當(dāng)前選中 mPaint.setTextSize(mMinTextSize + (mMaxTextSize - mMinTextSize) * (itemSize - Math.abs(moveLength)) / itemSize); } else if (relative == 1) { // 下一個(gè) if (moveLength > 0) { // 向下滑動(dòng) mPaint.setTextSize(mMinTextSize); } else { // 向上滑動(dòng) 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()) { // 水平滾動(dòng) x = top + (getItemWidth() - lineWidth) / 2; y = (getItemHeight() - layout.getHeight()) / 2; } else { // 垂直滾動(dòng) x = (getItemWidth() - lineWidth) / 2; y = top + (getItemHeight() - layout.getHeight()) / 2; } // 計(jì)算漸變顏色 computeColor(relative, itemSize, moveLength,text); // canvas.drawText(text, x, y, mPaint); canvas.save(); canvas.translate(x, y); layout.draw(canvas); canvas.restore(); } /** * 計(jì)算字體顏色,漸變 * * @param relative 相對(duì)中間item的位置 */ private String lastString; private String nowSring; private void computeColor(int relative, int itemSize, float moveLength, CharSequence text) { int color = mEndColor; // 其他默認(rèn)為mEndColor if (relative == -1 || relative == 1) { // 上一個(gè)或下一個(gè) // 處理上一個(gè)item且向上滑動(dòng) 或者 處理下一個(gè)item且向下滑動(dòng) ,顏色為mEndColor if ((relative == -1 && moveLength < 0) || (relative == 1 && moveLength > 0)) { color = mEndColor; } else { // 計(jì)算漸變的顏色 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; /** * 滾動(dòng)選擇器,帶慣性滑動(dòng) */ public abstract class ScrollPickerView<T> extends View { private int mVisibleItemCount = 3; // 可見的item數(shù)量 private boolean mIsInertiaScroll = true; // 快速滑動(dòng)時(shí)是否慣性滾動(dòng)一段距離,默認(rèn)開啟 private boolean mIsCirculation = true; // 是否循環(huán)滾動(dòng),默認(rèn)開啟 /* 不允許父組件攔截觸摸事件,設(shè)置為true為不允許攔截,此時(shí)該設(shè)置才生效 當(dāng)嵌入到ScrollView等滾動(dòng)組件中,為了使該自定義滾動(dòng)選擇器可以正常工作,請(qǐng)?jiān)O(shè)置為true */ private boolean mDisallowInterceptTouch = false; private int mSelected; // 當(dāng)前選中的item下標(biāo) private int mLastSelected; // 當(dāng)前選中的item下標(biāo) private List<T> mData; private int mItemHeight = 0; // 每個(gè)條目的高度,當(dāng)垂直滾動(dòng)時(shí),高度=mMeasureHeight/mVisibleItemCount private int mItemWidth = 0; // 每個(gè)條目的寬度,當(dāng)水平滾動(dòng)時(shí),寬度=mMeasureWidth/mVisibleItemCount private int mItemSize; // 當(dāng)垂直滾動(dòng)時(shí),mItemSize = mItemHeight;水平滾動(dòng)時(shí),mItemSize = mItemWidth private int mCenterPosition = -1; // 中間item的位置,0<=mCenterPosition<mVisibleItemCount,默認(rèn)為 mVisibleItemCount / 2 private int mCenterY; // 中間item的起始坐標(biāo)y(不考慮偏移),當(dāng)垂直滾動(dòng)時(shí),y= mCenterPosition*mItemHeight private int mCenterX; // 中間item的起始坐標(biāo)x(不考慮偏移),當(dāng)垂直滾動(dòng)時(shí),x = mCenterPosition*mItemWidth private int mCenterPoint; // 當(dāng)垂直滾動(dòng)時(shí),mCenterPoint = mCenterY;水平滾動(dòng)時(shí),mCenterPoint = mCenterX private float mLastMoveY; // 觸摸的坐標(biāo)y private float mLastMoveX; // 觸摸的坐標(biāo)X private float mMoveLength = 0; // item移動(dòng)長(zhǎng)度,負(fù)數(shù)表示向上移動(dòng),正數(shù)表示向下移動(dòng) private GestureDetector mGestureDetector; private OnSelectedListener mListener; private Scroller mScroller; private boolean mIsFling; // 是否正在慣性滑動(dòng) private boolean mIsMovingCenter; // 是否正在滑向中間 // 可以把scroller看做模擬的觸屏滑動(dòng)操作,mLastScrollY為上次觸屏滑動(dòng)的坐標(biāo) private int mLastScrollY = 0; // Scroller的坐標(biāo)y private int mLastScrollX = 0; // Scroller的坐標(biāo)x private boolean mDisallowTouch = false; // 不允許觸摸 private Paint mPaint; // private Drawable mCenterItemBackground = null; // 中間選中item的背景色 private boolean mCanTap = true; // 單擊切換選項(xiàng)或觸發(fā)點(diǎn)擊監(jiān)聽器 private boolean mIsHorizontal = false; // 是否水平滾動(dòng) private boolean mDrawAllItem = false; // 是否繪制每個(gè)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--) { // 先從遠(yuǎn)離中間位置的item繪制,當(dāng)item內(nèi)容偏大時(shí),較近的item覆蓋在較遠(yuǎn)的上面 if (mDrawAllItem || i <= mCenterPosition + 1) { // 上面的items,相對(duì)位置為 -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) { // 非循環(huán)滾動(dòng) drawItem(canvas, mData, position, -i, mMoveLength, mCenterPoint + mMoveLength - i * mItemSize); } } if (mDrawAllItem || i <= mVisibleItemCount - mCenterPosition) { // 下面的items,相對(duì)位置為 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()) { // 非循環(huán)滾動(dòng) drawItem(canvas, mData, position, i, mMoveLength, mCenterPoint + mMoveLength + i * mItemSize); } } } // 選中的item drawItem(canvas, mData, mSelected, 0, mMoveLength, mCenterPoint + mMoveLength); } /** * 繪制item * * @param canvas * @param data 數(shù)據(jù)集 * @param position 在data數(shù)據(jù)集中的位置 * @param relative 相對(duì)中間item的位置,relative==0表示中間item,relative<0表示上(左)邊的item,relative>0表示下(右)邊的item * @param moveLength 中間item滾動(dòng)的距離,moveLength<0則表示向上(右)滾動(dòng)的距離,moveLength>0則表示向下(左)滾動(dòng)的距離 * @param top 當(dāng)前繪制item的坐標(biāo),當(dāng)垂直滾動(dòng)時(shí)為頂部y的坐標(biāo);當(dāng)水平滾動(dòng)時(shí)為item最左邊x的坐標(biāo) */ 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) { // 正在滾動(dòng) if (mIsHorizontal) { // 可以把scroller看做模擬的觸屏滑動(dòng)操作,mLastScrollX為上次滑動(dòng)的坐標(biāo) mMoveLength = mMoveLength + curr - mLastScrollX; mLastScrollX = curr; } else { // 可以把scroller看做模擬的觸屏滑動(dòng)操作,mLastScrollY為上次滑動(dòng)的坐標(biāo) mMoveLength = mMoveLength + curr - mLastScrollY; mLastScrollY = curr; } checkCirculation(); invalidate(); } else { // 滾動(dòng)完畢 mIsMovingCenter = false; mLastScrollY = 0; mLastScrollX = 0; // 直接居中,不通過動(dòng)畫 if (mMoveLength > 0) { //// 向下滑動(dòng) 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()) { // 正在滾動(dòng) if (mIsHorizontal) { // 可以把scroller看做模擬的觸屏滑動(dòng)操作,mLastScrollX為上次滑動(dòng)的坐標(biāo) mMoveLength = mMoveLength + mScroller.getCurrX() - mLastScrollX; } else { // 可以把scroller看做模擬的觸屏滑動(dòng)操作,mLastScrollY為上次滑動(dòng)的坐標(biāo) mMoveLength = mMoveLength + mScroller.getCurrY() - mLastScrollY; } mLastScrollY = mScroller.getCurrY(); mLastScrollX = mScroller.getCurrX(); checkCirculation(); // 檢測(cè)當(dāng)前選中的item invalidate(); } else { // 滾動(dòng)完畢 if (mIsFling) { mIsFling = false; moveToCenter(); // 滾動(dòng)到中間位置 } else if (mIsMovingCenter) { // 選擇完成,回調(diào)給監(jiān)聽器 mMoveLength = 0; mIsMovingCenter = false; mLastScrollY = 0; mLastScrollX = 0; notifySelected(true); } } } public void cancelScroll() { mLastScrollY = 0; mLastScrollX = 0; mIsFling = mIsMovingCenter = false; mScroller.abortAnimation(); stopAutoScroll(); } // 檢測(cè)當(dāng)前選擇的item位置 private void checkCirculation() { if (mMoveLength >= mItemSize) { // 向下滑動(dòng) // 該次滾動(dòng)距離中越過的item數(shù)量 int span = (int) (mMoveLength / mItemSize); mSelected -= span; if (mSelected < 0) { // 滾動(dòng)頂部,判斷是否循環(huán)滾動(dòng) if (mIsCirculation) { do { mSelected = mData.size() + mSelected; } while (mSelected < 0); // 當(dāng)越過的item數(shù)量超過一圈時(shí) mMoveLength = (mMoveLength - mItemSize) % mItemSize; } else { // 非循環(huán)滾動(dòng) mSelected = 0; mMoveLength = mItemSize; if (mIsFling) { // 停止慣性滑動(dòng),根據(jù)computeScroll()中的邏輯,下一步將調(diào)用moveToCenter() mScroller.forceFinished(true); } if (mIsMovingCenter) { // 移回中間位置 scroll(mMoveLength, 0); } } } else { mMoveLength = (mMoveLength - mItemSize) % mItemSize; } } else if (mMoveLength <= -mItemSize) { // 向上滑動(dòng) // 該次滾動(dòng)距離中越過的item數(shù)量 int span = (int) (-mMoveLength / mItemSize); mSelected += span; if (mSelected >= mData.size()) { // 滾動(dòng)末尾,判斷是否循環(huán)滾動(dòng) if (mIsCirculation) { do { mSelected = mSelected - mData.size(); } while (mSelected >= mData.size()); // 當(dāng)越過的item數(shù)量超過一圈時(shí) mMoveLength = (mMoveLength + mItemSize) % mItemSize; } else { // 非循環(huán)滾動(dòng) mSelected = mData.size() - 1; mMoveLength = -mItemSize; if (mIsFling) { // 停止慣性滑動(dòng),根據(jù)computeScroll()中的邏輯,下一步將調(diào)用moveToCenter() mScroller.forceFinished(true); } if (mIsMovingCenter) { // 移回中間位置 scroll(mMoveLength, 0); } } } else { mMoveLength = (mMoveLength + mItemSize) % mItemSize; } } } // 移動(dòng)到中間位置 private void moveToCenter() { if (!mScroller.isFinished() || mIsFling || mMoveLength == 0) { return; } cancelScroll(); // 向下滑動(dòng) 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); } } } } // 平滑滾動(dòng) 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(); } // 慣性滑動(dòng), private void fling(float from, float vel) { if (mIsHorizontal) { mLastScrollX = (int) from; mIsFling = true; // 最多可以慣性滑動(dòng)10個(gè)item mScroller.fling((int) from, 0, (int) vel, 0, -10 * mItemWidth, 10 * mItemWidth, 0, 0); } else { mLastScrollY = (int) from; mIsFling = true; // 最多可以慣性滑動(dòng)10個(gè)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) { // 告訴監(jiān)聽器選擇完畢 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(); /** * 自動(dòng)滾動(dòng)(必須設(shè)置為可循環(huán)滾動(dòng)) * * @param position * @param duration * @param speed 每毫秒移動(dòng)的像素點(diǎn) */ @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); // 圈數(shù) 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導(dǎo)致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; } } /** * 自動(dòng)滾動(dòng),默認(rèn)速度為 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); } /** * 自動(dòng)滾動(dòng) * * @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); } /** * 滾動(dòng)到指定位置 * * @param toPosition 需要滾動(dòng)到的位置 * @param duration 滾動(dòng)時(shí)間 * @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 需要滾動(dòng)到的位置 * @param duration 滾動(dòng)時(shí)間 * @param interpolator * @param canIntercept 能否終止?jié)L動(dòng),比如觸摸屏幕終止?jié)L動(dòng) */ @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(); } /** * 停止自動(dòng)滾動(dòng) */ @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; } } /** * 快速滑動(dòng)時(shí),慣性滑動(dòng)一段距離 * * @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(); // 記錄是否從滾動(dòng)狀態(tài)終止 // 點(diǎn)擊時(shí)取消所有滾動(dòng)效果 cancelScroll(); mLastMoveY = e.getY(); mLastMoveX = e.getX(); return true; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, final float velocityY) { // 慣性滑動(dòng) 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(); } /** * 是否允許父元素?cái)r截事件,設(shè)置true后可以保證在ScrollView下正常滾動(dòng) */ public void setDisallowInterceptTouch(boolean disallowInterceptTouch) { mDisallowInterceptTouch = disallowInterceptTouch; } public int getItemHeight() { return mItemHeight; } public int getItemWidth() { return mItemWidth; } /** * @return 當(dāng)垂直滾動(dòng)時(shí),mItemSize = mItemHeight;水平滾動(dòng)時(shí),mItemSize = mItemWidth */ public int getItemSize() { return mItemSize; } /** * @return 中間item的起始坐標(biāo)x(不考慮偏移), 當(dāng)垂直滾動(dòng)時(shí),x = mCenterPosition*mItemWidth */ public int getCenterX() { return mCenterX; } /** * @return 中間item的起始坐標(biāo)y(不考慮偏移), 當(dāng)垂直滾動(dòng)時(shí),y= mCenterPosition*mItemHeight */ public int getCenterY() { return mCenterY; } /** * @return 當(dāng)垂直滾動(dòng)時(shí),mCenterPoint = mCenterY;水平滾動(dòng)時(shí),mCenterPoint = mCenterX */ public int getCenterPoint() { return mCenterPoint; } public boolean isDisallowTouch() { return mDisallowTouch; } /** * 設(shè)置是否允許手動(dòng)觸摸滾動(dòng) * * @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的位置,默認(rèn)為 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; } /** * 設(shè)置 單擊切換選項(xiàng)或觸發(fā)點(diǎn)擊監(jiān)聽器 * * @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 { /** * 計(jì)算漸變后的顏色 * * @param startColor 開始顏色 * @param endColor 結(jié)束顏色 * @param rate 漸變率(0,1) * @return 漸變后的顏色,當(dāng)rate=0時(shí),返回startColor,當(dāng)rate=1時(shí)返回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)); } }
調(diào)用
/** * 溫度 */ 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("空調(diào)溫度===",temperature+""); setTemperature(temperature);//網(wǎng)絡(luò)請(qǐng)求方法 } });
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android懸浮窗屏蔽懸浮窗外部所有的點(diǎn)擊事件的實(shí)例代碼
這篇文章主要介紹了Android懸浮窗屏蔽懸浮窗外部所有的點(diǎn)擊事件實(shí)例代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-03-03Android 獲取drawable目錄圖片 并存入指定文件的步驟詳解
這篇文章主要介紹了Android 獲取drawable目錄圖片 并存入指定文件,本文分步驟通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03Android網(wǎng)絡(luò)請(qǐng)求框架Retrofit詳解
這篇文章主要為大家詳細(xì)介紹了Android網(wǎng)絡(luò)請(qǐng)求框架Retrofit,使用Retrofit2.0.0版本進(jìn)行實(shí)例演示,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08Android實(shí)現(xiàn)帶列表的地圖POI周邊搜索功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)帶列表的地圖POI周邊搜索功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-05-05Android實(shí)現(xiàn)語音合成與識(shí)別功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)語音合成與識(shí)別功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07Android中butterknife的使用與自動(dòng)化查找組件插件詳解
這篇文章主要給大家介紹了關(guān)于Android中butterknife的使用與自動(dòng)化查找組件插件的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10Android中實(shí)現(xiàn)圖文并茂的按鈕實(shí)例代碼
這篇文章主要介紹了Android中實(shí)現(xiàn)圖文并茂的按鈕實(shí)例代碼,代碼簡(jiǎn)單易懂,非常不錯(cuò),需要的朋友可以參考下2017-04-04