Android中怎么自定义View实现标签流效果
发表于:2025-02-04 作者:千家信息网编辑
千家信息网最后更新 2025年02月04日,本篇内容主要讲解"Android中怎么自定义View实现标签流效果",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Android中怎么自定义View实现标签
千家信息网最后更新 2025年02月04日Android中怎么自定义View实现标签流效果
本篇内容主要讲解"Android中怎么自定义View实现标签流效果",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Android中怎么自定义View实现标签流效果"吧!
一、概述
Android自定义View实现标签流效果,一行放不下时会自动换行,用户可以自己定义单个标签的样式,可以选中和取消,可以监听单个标签的点击事件,功能还算强大,可以满足大部分开发需求,值得推荐,效果图如下:
二、实现代码
1.自定义View
定义属性文件
FlowTagConfig.java
package com.czhappy.effectdemo.flowtag;import android.content.Context;import android.content.res.TypedArray;import android.util.AttributeSet;import com.czhappy.effectdemo.R;/** * Description: * User: chenzheng * Date: 2017/2/17 0017 * Time: 10:23 */public class FlowTagConfig { private static final int DEFAULT_LINE_SPACING = 5;//默认行间距 private static final int DEFAULT_TAG_SPACING = 10;//各个标签之间的默认距离 private static final int DEFAULT_FIXED_COLUMN_SIZE = 3; //默认列数 private int lineSpacing; private int tagSpacing; private int columnSize; private boolean isFixed; public FlowTagConfig(Context context,AttributeSet attrs){ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FlowTagView); try { lineSpacing = a.getDimensionPixelSize(R.styleable.FlowTagView_lineSpacing, DEFAULT_LINE_SPACING); tagSpacing = a.getDimensionPixelSize(R.styleable.FlowTagView_tagSpacing, DEFAULT_TAG_SPACING); columnSize = a.getInteger(R.styleable.FlowTagView_columnSize, DEFAULT_FIXED_COLUMN_SIZE); isFixed = a.getBoolean(R.styleable.FlowTagView_isFixed,false); } finally { a.recycle(); } } public int getLineSpacing() { return lineSpacing; } public void setLineSpacing(int lineSpacing) { this.lineSpacing = lineSpacing; } public int getTagSpacing() { return tagSpacing; } public void setTagSpacing(int tagSpacing) { this.tagSpacing = tagSpacing; } public int getColumnSize() { return columnSize; } public void setColumnSize(int columnSize) { this.columnSize = columnSize; } public boolean isFixed() { return isFixed; } public void setIsFixed(boolean isFixed) { this.isFixed = isFixed; }}
FlowTagView.java
package com.czhappy.effectdemo.flowtag;import android.content.Context;import android.database.DataSetObserver;import android.graphics.Canvas;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;/** * Description: * User: chenzheng * Date: 2017/2/17 0017 * Time: 10:23 */public class FlowTagView extends ViewGroup { private int mLineSpacing;//行间距 private int mTagSpacing;//各个标签之间的距离 private BaseAdapter mAdapter; private TagItemClickListener mListener; private DataChangeObserver mObserver; public FlowTagView(Context context) { super(context); init(context, null, 0); } public FlowTagView(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs, 0); } public FlowTagView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs, defStyle); } private void init(Context context, AttributeSet attrs, int defStyle) { //获取属性 FlowTagConfig config = new FlowTagConfig(context, attrs); mLineSpacing = config.getLineSpacing(); mTagSpacing = config.getTagSpacing(); } private void drawLayout() { if (mAdapter == null || mAdapter.getCount() == 0) { return; } this.removeAllViews(); for (int i = 0; i < mAdapter.getCount(); i++) { View view = mAdapter.getView(i,null,null); final int position = i; view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mListener != null) { mListener.itemClick(position); } } }); this.addView(view); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int wantHeight = 0; int wantWidth = resolveSize(0, widthMeasureSpec); int paddingLeft = getPaddingLeft(); int paddingRight = getPaddingRight(); int paddingTop = getPaddingTop(); int paddingBottom = getPaddingBottom(); int childLeft = paddingLeft; int childTop = paddingTop; int lineHeight = 0; //固定列的数量所需要的代码 for (int i = 0; i < getChildCount(); i++) { final View childView = getChildAt(i); LayoutParams params = childView.getLayoutParams(); childView.measure( getChildMeasureSpec(widthMeasureSpec, paddingLeft + paddingRight, params.width), getChildMeasureSpec(heightMeasureSpec, paddingTop + paddingBottom, params.height) ); //获取单个tag的宽高 int childHeight = childView.getMeasuredHeight(); int childWidth = childView.getMeasuredWidth(); lineHeight = Math.max(childHeight, lineHeight); //超过长度的新起一行 if (childLeft + childWidth + paddingRight > wantWidth) { childLeft = paddingLeft; childTop += mLineSpacing + childHeight; lineHeight = childHeight; } childLeft += childWidth + mTagSpacing; } wantHeight += childTop + lineHeight + paddingBottom; setMeasuredDimension(wantWidth, resolveSize(wantHeight, heightMeasureSpec)); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { //固定列的数量所需要的代码 int width = r - l; int paddingLeft = getPaddingLeft(); int paddingTop = getPaddingTop(); int paddingRight = getPaddingRight(); int childLeft = paddingLeft; int childTop = paddingTop; int lineHeight = 0; for (int i = 0; i < getChildCount(); i++) { final View childView = getChildAt(i); if (childView.getVisibility() == View.GONE) { continue; } int childWidth = childView.getMeasuredWidth(); int childHeight = childView.getMeasuredHeight(); lineHeight = Math.max(childHeight, lineHeight); if (childLeft + childWidth + paddingRight > width) { childLeft = paddingLeft; childTop += mLineSpacing + lineHeight; lineHeight = childHeight; } childView.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight); childLeft += childWidth + mTagSpacing; } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); } @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new LayoutParams(this.getContext(), attrs); } public void setAdapter(BaseAdapter adapter){ if (mAdapter == null){ mAdapter = adapter; if (mObserver == null){ mObserver = new DataChangeObserver(); mAdapter.registerDataSetObserver(mObserver); } drawLayout(); } } public void setItemClickListener(TagItemClickListener mListener) { this.mListener = mListener; } /** * 单击监听接口 */ public interface TagItemClickListener { void itemClick(int position); } class DataChangeObserver extends DataSetObserver { @Override public void onChanged() { FlowTagView.this.drawLayout(); } @Override public void onInvalidated() { super.onInvalidated(); } }}
2.测试类
FlowTagActivity.java
package com.czhappy.effectdemo.activity;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v7.app.AppCompatActivity;import com.czhappy.effectdemo.R;import com.czhappy.effectdemo.adapter.EvaluateAdapter;import com.czhappy.effectdemo.flowtag.FlowTagView;import com.czhappy.effectdemo.model.Evaluate;import java.util.ArrayList;import java.util.List;/** * Description: * User: chenzheng * Date: 2017/2/17 0017 * Time: 11:47 */public class FlowTagActivity extends AppCompatActivity { private FlowTagView mContainer; private EvaluateAdapter adapter; private ListchooseList = new ArrayList (); @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_flowtag); initView(); initData(); } private void initData() { List list = new ArrayList(); Evaluate e1 = new Evaluate("热情", "1"); Evaluate e2 = new Evaluate("服务周到", "2"); Evaluate e3 = new Evaluate("一般", "3"); Evaluate e4 = new Evaluate("技术活杠杠的", "4"); Evaluate e5 = new Evaluate("专业精通", "5"); Evaluate e6 = new Evaluate("只会吹牛逼", "6"); Evaluate e7 = new Evaluate("地下第一仅此一家", "7"); list.add(e1); list.add(e2); list.add(e3); list.add(e4); list.add(e5); list.add(e6); list.add(e7); adapter.setItems(list); } private void initView() { mContainer = (FlowTagView) this.findViewById(R.id.container); adapter = new EvaluateAdapter(this); mContainer.setAdapter(adapter); mContainer.setItemClickListener(new FlowTagView.TagItemClickListener() { @Override public void itemClick(int position) { Evaluate e = (Evaluate) adapter.getItem(position); e.is_choosed = !e.is_choosed; if(e.is_choosed){ chooseList.add(e); }else{ chooseList.remove(e); } adapter.notifyDataSetChanged(); } }); }}
EvaluateAdapter.java
package com.czhappy.effectdemo.adapter;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.TextView;import com.czhappy.effectdemo.R;import com.czhappy.effectdemo.model.Evaluate;import java.util.ArrayList;import java.util.List;/** * Description: * User: chenzheng * Date: 2017/2/17 0017 * Time: 11:43 */public class EvaluateAdapter extends BaseAdapter { private Context context; private LayoutInflater mInflater; private Listlist; public EvaluateAdapter(Context context) { this.context = context; this.mInflater = LayoutInflater.from(context); this.list = new ArrayList (); } public List getList(){ return list; } public void setItems(List list){ this.list = list; notifyDataSetChanged(); } @Override public int getCount() { return list == null ? 0 : list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { holder = new ViewHolder(); convertView = mInflater.inflate( R.layout.evaluate_grid_item, null); holder.evaluate_tv = (TextView)convertView.findViewById(R.id.evaluate_tv); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } final Evaluate ee = (Evaluate) getItem(position); holder.evaluate_tv.setText(ee.getName()); if(ee.is_choosed){ holder.evaluate_tv.setBackgroundResource(R.drawable.bg_round_corner_line_orange); }else{ holder.evaluate_tv.setBackgroundResource(R.drawable.bg_round_corner_line_gray); } return convertView; } private final class ViewHolder { private TextView evaluate_tv; }}
布局文件
bg_round_corner_line_orange.xml
bg_round_corner_line_gray.xml
到此,相信大家对"Android中怎么自定义View实现标签流效果"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
标签
效果
代码
之间
内容
单个
属性
数量
文件
行间
学习
监听
实用
强大
更深
周到
热情
一家
一行
专业
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
招商银行网络安全合作
工业软件开发笔记本
宁畅精细服务器
数据库缓存修改顺序
中小学网络安全计划
计划网络技术的主要方法
网络安全充电桩
关于宣传网络安全的标语
服务器数据库版本低
笔记本怎么改服务器名称
数据库的字段类型和长度设计
美国软件开发需求
政府办网络安全事件应急预案
八方网络安全
服务器维护主要工作
幼儿园网络安全校园日ppt
网络安全宣传活动总结怎么写
计算机三级考试网络技术考啥
嵌入式软件开发客户表情包
数据库备份的文件用什么打开
招商银行网络安全合作
著名软件开发语言
本地 数据库如何搭建
异常值数据库
天津网络安全办公室
事业单位计算机网络技术试题
广东电信佛山软件开发
网络安全职责规划
服务器管理器状态
中职计算机网络技术怎么样