Android自定义ViewGroup实现标签流效果
(福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun)
本文实例为大家分享了Android自定义ViewGroup实现标签流效果的具体代码,供大家参考,具体内容如下
自定义View,一是为了满足设计需求,二是开发者进阶的标志之一。随心所欲就是我等奋斗的目标!!!
效果
实现逻辑
明确需求
1、标签流效果;
2、可以动态添加标签;
3、标签需要有点击效果以及回调;
整理思路
既然要装载标签,就需要自定义ViewGroup ,而自定义ViewGroup 比较复杂的就是onLayout()中对子View的排版。既然是标签,在一行中一定要显示完整,在排版的时候注意这一点,需要添加判断!其次,标签要有点击事件,这里的实现我们可以借助子View的点击事件封装一个接口,实现我们自己的点击事件!
要点
1、对于子View的测量;
2、对于子View的排版;
Ps: 需要注意的是给子View设置背景Drawable的时候不可以设置同一个Drawable,否则会出现错乱情况!见getSonView()方法中完整代码
/** ?* 自定义ViewGroup实现标签流效果 ?* ?* @attr customInterval ?//标签之间的间隔 ?* @attr customSelectMode ?//标签选项模式 ?* @attr customSonBackground ? //标签背景 ?* @attr customSonPaddingBottom ? //标签底部内边距 ?* @attr customSonPaddingLeft ?//标签左边内边距 ?* @attr customSonPaddingRight ?//标签右边内边距 ?* @attr customSonPaddingTop ?//标签顶部内边距 ?* @attr customSonTextColor ?//标签文字颜色 ?* @attr customSonTextSize ?//标签文字尺寸 ?*/ public class CustomLableView extends ViewGroup { ? ? private static final String TAG = "CustomLableView"; ? ? private int customInterval = 15; ? ? private int customSonPaddingLeft = 20; ? ? private int customSonPaddingRight = 20; ? ? private int customSonPaddingTop = 10; ? ? private int customSonPaddingBottom = 10; ? ? private Drawable customSonBackground = null; ? ? private float customSonTextSize = 0; ? ? private ColorStateList customSonTextColor = ColorStateList.valueOf(0xFF000000); ? ? private ArrayList<String> mSonTextContents = new ArrayList<>(); ? ? private ArrayList<TextView> mSonTextViews = new ArrayList<>(); ? ? private Context mContext = null; ? ? private OnItemClickListener mOnItemClickListener; ? ? private int customSelectMode; ? ? public CustomLableView(Context context) { ? ? ? ? this(context, null); ? ? } ? ? public CustomLableView(Context context, AttributeSet attrs) { ? ? ? ? this(context, attrs, 0); ? ? } ? ? public CustomLableView(Context context, AttributeSet attrs, int defStyleAttr) { ? ? ? ? super(context, attrs, defStyleAttr); ? ? ? ? this.mContext = context; ? ? ? ? //初始化自定义属性 ? ? ? ? initAttrs(context, attrs); ? ? } ? ? @Override ? ? protected void onLayout(boolean changed, int l, int t, int r, int b) { ? ? ? ? int left = customInterval; ? ? ? ? int top = customInterval; ? ? ? ? int mMeasuredWidth = this.getMeasuredWidth(); ? ? ? ? //防止重复添加 ? ? ? ? CustomLableView.this.removeAllViews(); ? ? ? ? for (int i = 0; i < mSonTextViews.size(); i++) { ? ? ? ? ? ? final TextView mTextView = mSonTextViews.get(i); ? ? ? ? ? ? //将当前子View添加到ViewGroup中 ? ? ? ? ? ? CustomLableView.this.addView(mTextView); ? ? ? ? ? ? //获取当前子View的宽高 ? ? ? ? ? ? int measuredHeight = mTextView.getMeasuredHeight(); ? ? ? ? ? ? int measuredWidth = mTextView.getMeasuredWidth(); ? ? ? ? ? ? //判断一行是否可显示 ? ? ? ? ? ? if ((mMeasuredWidth - left) >= (measuredWidth + customInterval * 2)) {//一行可显示 ? ? ? ? ? ? ? ? /** ? ? ? ? ? ? ? ? ?* 1、(mMeasuredWidth - left) X轴剩余空间 ? ? ? ? ? ? ? ? ?* 2、(measuredWidth + customInterval * 2) 当前子View和间隔需要的空间 ? ? ? ? ? ? ? ? ?*/ ? ? ? ? ? ? ? ? mTextView.layout(left, top, left + measuredWidth, top + measuredHeight); ? ? ? ? ? ? ? ? left += (measuredWidth + customInterval); ? ? ? ? ? ? } else {//需要换行显示 ? ? ? ? ? ? ? ? //还原X轴的起始位置 ? ? ? ? ? ? ? ? left = customInterval; ? ? ? ? ? ? ? ? //Y轴高度增加 ? ? ? ? ? ? ? ? top += (measuredHeight + customInterval); ? ? ? ? ? ? ? ? mTextView.layout(left, top, left + measuredWidth, top + measuredHeight); ? ? ? ? ? ? ? ? left += (measuredWidth + customInterval); ? ? ? ? ? ? } ? ? ? ? } ? ? } ? ? @Override ? ? protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { ? ? ? ? super.onMeasure(widthMeasureSpec, heightMeasureSpec); ? ? ? ? //控件宽度 ? ? ? ? int mMeasureViewWidht = MeasureSpec.getSize(widthMeasureSpec); ? ? ? ? //显示行数 ? ? ? ? int line = 1; ? ? ? ? //每行当前宽度 ? ? ? ? int lineWidht = customInterval; ? ? ? ? //每行高度(子View的高度) ? ? ? ? int mSonMeasuredHeight = 0; ? ? ? ? mSonTextViews.clear(); ? ? ? ? for (int i = 0; i < mSonTextContents.size(); i++) { ? ? ? ? ? ? TextView mSonView = getSonView(i, mSonTextContents.get(i)); ? ? ? ? ? ? //对子View进行测量 ? ? ? ? ? ? mSonView.measure(0, 0); ? ? ? ? ? ? //获取子View的测量尺寸 ? ? ? ? ? ? int mSonMeasuredWidth = mSonView.getMeasuredWidth() + customInterval; ? ? ? ? ? ? mSonMeasuredHeight = mSonView.getMeasuredHeight() + customInterval; ? ? ? ? ? ? //添加到数组中 ? ? ? ? ? ? mSonTextViews.add(mSonView); ? ? ? ? ? ? if (mMeasureViewWidht >= mSonMeasuredWidth) { ? ? ? ? ? ? ? ? if ((mMeasureViewWidht - lineWidht) >= mSonMeasuredWidth) { ? ? ? ? ? ? ? ? ? ? lineWidht += mSonMeasuredWidth; ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? //行数自加1 ? ? ? ? ? ? ? ? ? ? line += 1; ? ? ? ? ? ? ? ? ? ? lineWidht = customInterval + mSonMeasuredWidth; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? mSonTextViews.clear(); ? ? ? ? ? ? ? ? setMeasuredDimension(0, 0); ? ? ? ? ? ? ? ? return; ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? //设置控件尺寸 ? ? ? ? setMeasuredDimension(mMeasureViewWidht, mSonMeasuredHeight * line + customInterval); ? ? } ? ? /** ? ? ?* 设置标签内容集合 ? ? ?* ? ? ?* @param sonContent 标签内容 ? ? ?*/ ? ? public void setSonContent(ArrayList<String> sonContent) { ? ? ? ? if (sonContent != null) { ? ? ? ? ? ? mSonTextContents.clear(); ? ? ? ? ? ? mSonTextContents.addAll(sonContent); ? ? ? ? ? ? requestLayout(); ? ? ? ? } ? ? } ? ? /** ? ? ?* 添加一个标签 ? ? ?* ? ? ?* @param sonContent 标签内容 ? ? ?*/ ? ? public void addSonContent(String sonContent) { ? ? ? ? if (!TextUtils.isEmpty(sonContent)) { ? ? ? ? ? ? mSonTextContents.add(0, sonContent); ? ? ? ? ? ? requestLayout(); ? ? ? ? } ? ? } ? ? /** ? ? ?* 设置标签点击事件 ? ? ?* ? ? ?* @param onItemClickListener 回调接口 ? ? ?*/ ? ? public void setOnItemClickListener(OnItemClickListener onItemClickListener) { ? ? ? ? this.mOnItemClickListener = onItemClickListener; ? ? } ? ? /** ? ? ?* 获取子View ? ? ?* ? ? ?* @return TextView ? ? ?*/ ? ? private TextView getSonView(final int i, final String content) { ? ? ? ? if (mContext != null) { ? ? ? ? ? ? TextView mTextView = new TextView(mContext); ? ? ? ? ? ? mTextView.setTextColor(customSonTextColor); ? ? ? ? ? ? mTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, customSonTextSize); ? ? ? ? ? ? //不可以设置相同的Drawable ? ? ? ? ? ? mTextView.setBackgroundDrawable(customSonBackground.getConstantState().newDrawable()); ? ? ? ? ? ? mTextView.setText(content); ? ? ? ? ? ? mTextView.setPadding(customSonPaddingLeft, customSonPaddingTop, customSonPaddingRight, customSonPaddingBottom); ? ? ? ? ? ? //消除TextView默认的上下内边距 ? ? ? ? ? ? mTextView.setIncludeFontPadding(false); ? ? ? ? ? ? mTextView.setOnClickListener(new OnClickListener() { ? ? ? ? ? ? ? ? @Override ? ? ? ? ? ? ? ? public void onClick(View v) { ? ? ? ? ? ? ? ? ? ? //选择模式 ? ? ? ? ? ? ? ? ? ? if (customSelectMode != 102) { ? ? ? ? ? ? ? ? ? ? ? ? for (int j = 0; j < mSonTextViews.size(); j++) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? mSonTextViews.get(j).setSelected(false); ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? v.setSelected(true); ? ? ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? ? ? v.setSelected(true); ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? if (mOnItemClickListener != null) { ? ? ? ? ? ? ? ? ? ? ? ? mOnItemClickListener.onItemClick(v, i, content); ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? } ? ? ? ? ? ? }); ? ? ? ? ? ? return mTextView; ? ? ? ? } ? ? ? ? return null; ? ? } ? ? /** ? ? ?* 初始化自定义属性 ? ? ?* ? ? ?* @param context ? ? ?* @param attrs ? ? ?*/ ? ? private void initAttrs(Context context, AttributeSet attrs) { ? ? ? ? TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomLableView); ? ? ? ? customSonBackground = mTypedArray.getDrawable(R.styleable.CustomLableView_customSonBackground); ? ? ? ? customInterval = (int) mTypedArray.getDimension(R.styleable.CustomLableView_customInterval, customInterval); ? ? ? ? customSonPaddingLeft = (int) mTypedArray.getDimension(R.styleable.CustomLableView_customSonPaddingLeft, customSonPaddingLeft); ? ? ? ? customSonPaddingRight = (int) mTypedArray.getDimension(R.styleable.CustomLableView_customSonPaddingRight, customSonPaddingRight); ? ? ? ? customSonPaddingTop = (int) mTypedArray.getDimension(R.styleable.CustomLableView_customSonPaddingTop, customSonPaddingTop); ? ? ? ? customSonPaddingBottom = (int) mTypedArray.getDimension(R.styleable.CustomLableView_customSonPaddingBottom, customSonPaddingBottom); ? ? ? ? customSonTextSize = (int) mTypedArray.getDimension(R.styleable.CustomLableView_customSonTextSize, 0); ? ? ? ? customSonTextColor = mTypedArray.getColorStateList(R.styleable.CustomLableView_customSonTextColor); ? ? ? ? customSelectMode = mTypedArray.getInt(R.styleable.CustomLableView_customSelectMode, 101); ? ? ? ? if (customSonTextSize == 0) { ? ? ? ? ? ? customSonTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 14, getResources().getDisplayMetrics()); ? ? ? ? } ? ? ? ? mTypedArray.recycle(); ? ? } ? ? public interface OnItemClickListener { ? ? ? ? void onItemClick(View view, int position, String sonContent); ? ? } }
自定义属性
<declare-styleable name="CustomLableView"> ? ? ? ? <attr name="customSonBackground" format="reference" /> ? ? ? ? <attr name="customInterval" format="dimension" /> ? ? ? ? <attr name="customSonPaddingLeft" format="dimension" /> ? ? ? ? <attr name="customSonPaddingRight" format="dimension" /> ? ? ? ? <attr name="customSonPaddingTop" format="dimension" /> ? ? ? ? <attr name="customSonPaddingBottom" format="dimension" /> ? ? ? ? <attr name="customSonTextSize" format="dimension" /> ? ? ? ? <attr name="customSonTextColor" format="color" /> ? ? ? ? <attr name="customSelectMode"> ? ? ? ? ? ? <enum name="alone" value="101" /> ? ? ? ? ? ? <enum name="multi" value="102" /> ? ? ? ? </attr> </declare-styleable>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持程序员之家。
相关文章
Android中TextView和ImageView实现倾斜效果
这篇文章主要为大家详细介绍了Android中TextView和ImageView实现倾斜效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下2017-08-08
最新评论