iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Android中怎么自定义View实现标签流效果
  • 904
分享到

Android中怎么自定义View实现标签流效果

2023-06-29 05:06:24 904人浏览 八月长安
摘要

本篇内容主要讲解“Android中怎么自定义View实现标签流效果”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Android中怎么自定义View实现标签流效果”吧!一、概述Android自定义

本篇内容主要讲解“Android中怎么自定义View实现标签流效果”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Android中怎么自定义View实现标签流效果”吧!

一、概述

Android自定义View实现标签流效果,一行放不下时会自动换行,用户可以自己定义单个标签的样式,可以选中和取消,可以监听单个标签的点击事件,功能还算强大,可以满足大部分开发需求,值得推荐,效果图如下:

Android中怎么自定义View实现标签流效果

二、实现代码

1.自定义View

定义属性文件

<declare-styleable name="FlowTagView">        <attr name="lineSpacing" fORMat="dimension" />        <attr name="tagSpacing" format="dimension" />        <!-- 是否是固定布局 -->        <attr name="isFixed" format="boolean" />        <attr name="columnSize" format="integer" /></declare-styleable>

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;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;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;public class FlowTagActivity extends AppCompatActivity {    private FlowTagView mContainer;    private EvaluateAdapter adapter;    private List<Evaluate> chooseList = new ArrayList<Evaluate>();    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_flowtag);        initView();        initData();    }    private void initData() {        List<Evaluate> 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;public class EvaluateAdapter extends BaseAdapter {    private Context context;    private LayoutInflater mInflater;    private List<Evaluate> list;    public EvaluateAdapter(Context context) {        this.context = context;        this.mInflater = LayoutInflater.from(context);        this.list =  new ArrayList<Evaluate>();    }    public List<Evaluate> getList(){        return list;    }    public void setItems(List<Evaluate> 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;    }}

布局文件

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="Http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <com.czhappy.effectdemo.flowtag.FlowTagView        android:id="@+id/container"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:padding="10dp"        app:tagSpacing="10dp"        app:lineSpacing="10dp"/></LinearLayout>

bg_round_corner_line_orange.xml

<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" >    <solid android:color="#ffffff" />    <corners android:radius="5dp" />    <stroke android:width="0.5dp"        android:color="#FF6700"/></shape>

bg_round_corner_line_gray.xml

<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" >    <solid android:color="#ffffff" />    <corners android:radius="5dp" />    <stroke android:width="0.5dp"        android:color="#cccccc"/></shape>

到此,相信大家对“Android中怎么自定义View实现标签流效果”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: Android中怎么自定义View实现标签流效果

本文链接: https://www.lsjlt.com/news/322709.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++ 生态系统中流行库和框架的贡献指南
    作为 c++++ 开发人员,通过遵循以下步骤即可为流行库和框架做出贡献:选择一个项目并熟悉其代码库。在 issue 跟踪器中寻找适合初学者的问题。创建一个新分支,实现修复并添加测试。提交...
    99+
    2024-05-15
    框架 c++ 流行库 git
  • C++ 生态系统中流行库和框架的社区支持情况
    c++++生态系统中流行库和框架的社区支持情况:boost:活跃的社区提供广泛的文档、教程和讨论区,确保持续的维护和更新。qt:庞大的社区提供丰富的文档、示例和论坛,积极参与开发和维护。...
    99+
    2024-05-15
    生态系统 社区支持 c++ overflow 标准库
  • c++中if elseif使用规则
    c++ 中 if-else if 语句的使用规则为:语法:if (条件1) { // 执行代码块 1} else if (条件 2) { // 执行代码块 2}// ...else ...
    99+
    2024-05-15
    c++
  • c++中的继承怎么写
    继承是一种允许类从现有类派生并访问其成员的强大机制。在 c++ 中,继承类型包括:单继承:一个子类从一个基类继承。多继承:一个子类从多个基类继承。层次继承:多个子类从同一个基类继承。多层...
    99+
    2024-05-15
    c++
  • c++中如何使用类和对象掌握目标
    在 c++ 中创建类和对象:使用 class 关键字定义类,包含数据成员和方法。使用对象名称和类名称创建对象。访问权限包括:公有、受保护和私有。数据成员是类的变量,每个对象拥有自己的副本...
    99+
    2024-05-15
    c++
  • c++中优先级是什么意思
    c++ 中的优先级规则:优先级高的操作符先执行,相同优先级的从左到右执行,括号可改变执行顺序。操作符优先级表包含从最高到最低的优先级列表,其中赋值运算符具有最低优先级。通过了解优先级,可...
    99+
    2024-05-15
    c++
  • c++中a+是什么意思
    c++ 中的 a+ 运算符表示自增运算符,用于将变量递增 1 并将结果存储在同一变量中。语法为 a++,用法包括循环和计数器。它可与后置递增运算符 ++a 交换使用,后者在表达式求值后递...
    99+
    2024-05-15
    c++
  • c++中a.b什么意思
    c++kquote>“a.b”表示对象“a”的成员“b”,用于访问对象成员,可用“对象名.成员名”的语法。它还可以用于访问嵌套成员,如“对象名.嵌套成员名.成员名”的语法。 c++...
    99+
    2024-05-15
    c++
  • C++ 并发编程库的优缺点
    c++++ 提供了多种并发编程库,满足不同场景下的需求。线程库 (std::thread) 易于使用但开销大;异步库 (std::async) 可异步执行任务,但 api 复杂;协程库 ...
    99+
    2024-05-15
    c++ 并发编程
  • 如何在 Golang 中备份数据库?
    在 golang 中备份数据库对于保护数据至关重要。可以使用标准库中的 database/sql 包,或第三方包如 github.com/go-sql-driver/mysql。具体步骤...
    99+
    2024-05-15
    golang 数据库备份 mysql git 标准库
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作