SegmentControl的实现与使用
来源:互联网 发布:防伪码生成算法php 编辑:程序博客网 时间:2024/06/08 14:37
发现问题
Android中并没有分段选择器这一控件,如果我们想通过点击而不是滑动的方式来控制碎片的切换,我们可以自己实现SegmentControl。
SegmentControl的实现
res/values/attras
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="SegmentControl"> <attr name="cornerRadius" format="dimension|reference" /> <attr name="colors" format="color|reference" /> <attr name="texts" format="string|reference" /> <attr name="android:textSize" /> <attr name="direction" format="enum"> <enum name="horizon" value="0" /> <enum name="vertical" value="1" /> </attr> <attr name="gaps" format="dimension|reference" /> <attr name="horizonGap" format="dimension|reference" /> <attr name="verticalGap" format="dimension|reference" /> </declare-styleable></resources>
SegmentControl.java
import com.app.cloud.R;import android.content.Context;import android.content.res.ColorStateList;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Rect;import android.os.Build;import android.util.AttributeSet;import android.util.TypedValue;import android.view.MotionEvent;import android.view.View;import android.view.ViewConfiguration;public class SegmentControl extends View { private String[] mTexts; private Rect[] mCacheBounds; private Rect[] mTextBounds; private RadiusDrawable mBackgroundDrawable; private RadiusDrawable mSelectedDrawable; private int mCurrentIndex; private int mTouchSlop; private boolean inTapRegion; private float mStartX; private float mStartY; private float mCurrentX; private float mCurrentY; private int mHorizonGap; private int mVerticalGap; private int mCenterX; private int mCenterY; private int mChildrenWidth; private int mChildrenHeight; private int mSingleChildWidth; private int mSingleChildHeight; private Paint mPaint; public enum Direction { HORIZON(0), VERTICAL(1); int mV; private Direction(int v) { mV = v; } } private Direction mDirection; private int mTextSize; private ColorStateList mColors; private int mCornerRadius; public interface OnSegmentControlClickListener { public void onSegmentControlClick(int index); } private OnSegmentControlClickListener mOnSegmentControlClickListener; public SegmentControl(Context context) { this(context, null); } public SegmentControl(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SegmentControl(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SegmentControl); String textArray = ta.getString(R.styleable.SegmentControl_texts); if (textArray != null) { mTexts = textArray.split("\\|"); } mTextSize = ta.getDimensionPixelSize(R.styleable.SegmentControl_android_textSize, (int) TypedValue .applyDimension(TypedValue.COMPLEX_UNIT_SP, 14, context.getResources().getDisplayMetrics())); mColors = ta.getColorStateList(R.styleable.SegmentControl_colors); mCornerRadius = ta.getDimensionPixelSize(R.styleable.SegmentControl_cornerRadius, (int) TypedValue .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, context.getResources().getDisplayMetrics())); mDirection = Direction.values()[ta.getInt(R.styleable.SegmentControl_direction, 0)]; mHorizonGap = ta.getDimensionPixelSize(R.styleable.SegmentControl_horizonGap, 0); mVerticalGap = ta.getDimensionPixelSize(R.styleable.SegmentControl_verticalGap, 0); int gap = ta.getDimensionPixelSize(R.styleable.SegmentControl_gaps, (int) TypedValue .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, context.getResources().getDisplayMetrics())); if (mHorizonGap == 0) mHorizonGap = gap; if (mVerticalGap == 0) mVerticalGap = gap; ta.recycle(); mBackgroundDrawable = new RadiusDrawable(mCornerRadius, true, 0); mBackgroundDrawable.setStrokeWidth(2); if (mColors == null) { mColors = new ColorStateList(new int[][] { {} }, new int[] { 0xFF0099CC }); } mBackgroundDrawable.setStrokeColor(mColors.getDefaultColor()); if (Build.VERSION.SDK_INT < 16) { setBackgroundDrawable(mBackgroundDrawable); } else { setBackground(mBackgroundDrawable); } mSelectedDrawable = new RadiusDrawable(mCornerRadius, false, mColors.getDefaultColor()); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setTextSize(mTextSize); mPaint.setColor(mColors.getDefaultColor()); // here's the tricky thing, when you doing a click detect on a // capacitive touch screen, // sometimes the touch points of touchDown and touchUp are // different(it's call slop) even when you didn't actually move your // finger, // so we set a distance limit for the distance of this two touch points // to create a better user experience; int touchSlop = 0; if (context == null) { touchSlop = ViewConfiguration.getTouchSlop(); } else { final ViewConfiguration config = ViewConfiguration.get(context); touchSlop = config.getScaledTouchSlop(); } mTouchSlop = touchSlop * touchSlop; inTapRegion = false; } public void setOnSegmentControlClickListener(OnSegmentControlClickListener onSegmentControlClickListener) { mOnSegmentControlClickListener = onSegmentControlClickListener; } public OnSegmentControlClickListener getOnSegmentControlClicklistener() { return mOnSegmentControlClickListener; } public void setText(String... texts) { mTexts = texts; if (mTexts != null) { requestLayout(); } } public void setColors(ColorStateList colors) { mColors = colors; if (mBackgroundDrawable != null) { mBackgroundDrawable.setStrokeColor(colors.getDefaultColor()); } if (mSelectedDrawable != null) { mSelectedDrawable.setColor(colors.getDefaultColor()); } mPaint.setColor(colors.getDefaultColor()); invalidate(); } public void setCornerRadius(int cornerRadius) { mCornerRadius = cornerRadius; if (mBackgroundDrawable != null) { mBackgroundDrawable.setRadius(cornerRadius); } invalidate(); } public void setDirection(Direction direction) { Direction tDirection = mDirection; mDirection = direction; if (tDirection != direction) { requestLayout(); invalidate(); } } public void setTextSize(int textSize) { setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize); } public void setTextSize(int unit, int textSize) { mPaint.setTextSize( (int) (TypedValue.applyDimension(unit, textSize, getContext().getResources().getDisplayMetrics()))); if (textSize != mTextSize) { mTextSize = textSize; requestLayout(); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int width = 0; int height = 0; if (mTexts != null && mTexts.length > 0) { if (mCacheBounds == null || mCacheBounds.length != mTexts.length) { mCacheBounds = new Rect[mTexts.length]; } if (mTextBounds == null || mTextBounds.length != mTexts.length) { mTextBounds = new Rect[mTexts.length]; } for (int i = 0; i < mTexts.length; i++) { String text = mTexts[i]; if (text != null) { if (mTextBounds[i] == null) mTextBounds[i] = new Rect(); mPaint.getTextBounds(text, 0, text.length(), mTextBounds[i]); if (mSingleChildWidth < mTextBounds[i].width() + mHorizonGap * 2) mSingleChildWidth = mTextBounds[i].width() + mHorizonGap * 2; if (mSingleChildHeight < mTextBounds[i].height() + mVerticalGap * 2) mSingleChildHeight = mTextBounds[i].height() + mVerticalGap * 2; } } for (int i = 0; i < mTexts.length; i++) { if (mCacheBounds[i] == null) mCacheBounds[i] = new Rect(); if (mDirection == Direction.HORIZON) { mCacheBounds[i].left = i * mSingleChildWidth; mCacheBounds[i].top = 0; } else { mCacheBounds[i].left = 0; mCacheBounds[i].top = i * mSingleChildHeight; } mCacheBounds[i].right = mCacheBounds[i].left + mSingleChildWidth; mCacheBounds[i].bottom = mCacheBounds[i].top + mSingleChildHeight; } switch (widthMode) { case MeasureSpec.AT_MOST: if (mDirection == Direction.HORIZON) { if (widthSize <= mSingleChildWidth * mTexts.length) { mSingleChildWidth = widthSize / mTexts.length; width = widthSize; } else { width = mSingleChildWidth * mTexts.length; } } else { width = widthSize <= mSingleChildWidth ? widthSize : mSingleChildWidth; } break; case MeasureSpec.EXACTLY: width = widthSize; break; case MeasureSpec.UNSPECIFIED: if (mDirection == Direction.HORIZON) { width = mSingleChildWidth * mTexts.length; } else { width = widthSize <= mSingleChildWidth ? widthSize : mSingleChildWidth; } break; } switch (heightMode) { case MeasureSpec.AT_MOST: if (mDirection == Direction.VERTICAL) { if (heightSize <= mSingleChildHeight * mTexts.length) { mSingleChildHeight = heightSize / mTexts.length; height = heightSize; } else { height = mSingleChildHeight * mTexts.length; } } else { height = heightSize <= mSingleChildHeight ? heightSize : mSingleChildHeight; } break; case MeasureSpec.EXACTLY: height = heightSize; break; case MeasureSpec.UNSPECIFIED: if (mDirection == Direction.VERTICAL) { height = mSingleChildHeight * mTexts.length; } else { height = heightSize <= mSingleChildHeight ? heightSize : mSingleChildHeight; } break; } mChildrenWidth = mDirection == Direction.HORIZON ? mSingleChildWidth * mTexts.length : mSingleChildWidth; mChildrenHeight = mDirection == Direction.VERTICAL ? mSingleChildHeight * mTexts.length : mSingleChildHeight; } else { width = widthMode == MeasureSpec.UNSPECIFIED ? 0 : widthSize; height = heightMode == MeasureSpec.UNSPECIFIED ? 0 : heightSize; } mCenterX = width / 2; mCenterY = height / 2; setMeasuredDimension(width, height); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: inTapRegion = true; mStartX = event.getX(); mStartY = event.getY(); break; case MotionEvent.ACTION_MOVE: mCurrentX = event.getX(); mCurrentY = event.getY(); int dx = (int) (mCurrentX - mStartX); int dy = (int) (mCurrentY - mStartY); int distance = dx * dx + dy * dy; if (distance > mTouchSlop) { inTapRegion = false; } break; case MotionEvent.ACTION_UP: if (inTapRegion) { int index = 0; if (mDirection == Direction.HORIZON) { index = (int) (mStartX / mSingleChildWidth); } else { index = (int) (mStartY / mSingleChildHeight); } if (mOnSegmentControlClickListener != null) mOnSegmentControlClickListener.onSegmentControlClick(index); mCurrentIndex = index; invalidate(); } break; } return true; } public void setSelectedIndex(int index) { mCurrentIndex = index; invalidate(); } @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); if (mTexts != null && mTexts.length > 0) { for (int i = 0; i < mTexts.length; i++) { // draw separate lines if (i < mTexts.length - 1) { mPaint.setColor(mColors.getDefaultColor()); if (mDirection == Direction.HORIZON) { canvas.drawLine(mCacheBounds[i].right, 0, mCacheBounds[i].right, getHeight(), mPaint); } else { canvas.drawLine(mCacheBounds[i].left, mSingleChildHeight * (i + 1), mCacheBounds[i].right, mSingleChildHeight * (i + 1), mPaint); } } // draw selected drawable if (i == mCurrentIndex && mSelectedDrawable != null) { int topLeftRadius = 0; int topRightRadius = 0; int bottomLeftRadius = 0; int bottomRightRadius = 0; if (mDirection == Direction.HORIZON) { if (i == 0) { topLeftRadius = mCornerRadius; bottomLeftRadius = mCornerRadius; } else if (i == mTexts.length - 1) { topRightRadius = mCornerRadius; bottomRightRadius = mCornerRadius; } } else { if (i == 0) { topLeftRadius = mCornerRadius; topRightRadius = mCornerRadius; } else if (i == mTexts.length - 1) { bottomLeftRadius = mCornerRadius; bottomRightRadius = mCornerRadius; } } mSelectedDrawable.setRadiuses(topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius); mSelectedDrawable.setBounds(mCacheBounds[i]); mSelectedDrawable.draw(canvas); mPaint.setColor(0xFFFFFFFF); } else { mPaint.setColor(mColors.getDefaultColor()); } // draw texts canvas.drawText(mTexts[i], mCacheBounds[i].left + (mSingleChildWidth - mTextBounds[i].width()) / 2, mCacheBounds[i].top + ((mSingleChildHeight + mTextBounds[i].height()) / 2), mPaint); } } }}
SegmentControl的使用
<com.app.cloud.Ui.SegmentControl xmlns:segmentcontrol="http://schemas.android.com/apk/res-auto" android:id="@+id/segment_control" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_margin="8dp" android:textSize="15sp" segmentcontrol:colors="#1E90FF" segmentcontrol:cornerRadius="5dip" segmentcontrol:horizonGap="35dip" segmentcontrol:texts="全国|同城|个人" segmentcontrol:verticalGap="10dip" />
SegmentControl segment;segment = (SegmentControl) view.findViewById(R.id.segment_control);segment.setOnSegmentControlClickListener(new OnSegmentControlClickListener() { @Override public void onSegmentControlClick(int index) { //TODO index点击下标事件 }});
效果
作者:吴艺
链接:SegmentControl的实现与使用
阅读全文
0 0
- SegmentControl的实现与使用
- SegmentControl的实现与使用
- segmentControl实现控制器的切换
- iOS: SegmentControl 实现页面切换的四种方法
- iOS: SegmentControl 实现页面切换的四种方法
- 利用视错觉原理实现一个自定义的SegmentControl
- iOS: SegmentControl 实现页面切换的四种方法
- SegmentControl的基本设置
- SegmentControl的基本设置
- segmentcontrol
- SegMentControl
- SegmentControl
- segmentControl 在IOS5 使用问题
- Ios使用按钮自定义segmentcontrol
- Ios使用按钮自定义segmentcontrol
- iOS SegmentControl的基本设置
- 第三方SegmentControl+fragment实现选择切换
- SegmentControl 那些令人烦恼的事儿
- Xml教程01_简介
- http post 模板 (设置header + json传参)
- window下mysql本地修改密码
- CXF发布RestFul WebService和SOAP WebService
- 打印开机过程中启动init 命令
- SegmentControl的实现与使用
- 初识Hadoop
- Java基础语法
- SQL语言的四大功能
- WebView的详细介绍
- JAVA 转换时间格式以及比较时间大小
- HBase Minor&Major Compaction 解析
- AndroidImageSlider实现广告轮播条
- 线程