In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-09 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly explains "how to customize View in Android to achieve label flow effect", interested friends may wish to have a look. The method introduced in this paper is simple, fast and practical. Next let the editor to take you to learn "how to customize View in Android to achieve label flow effect"!
I. Overview
Android custom View implements tag stream effect. When a line cannot be placed, it automatically wraps lines. Users can define the style of a single tag, select and cancel it, and listen for click events of a single tag. The function is powerful and can meet most development needs. It is recommended. The effect is as follows:
Second, implementation code
1. Custom View
Define properties file
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_LINE_SPACING / default row spacing private static final int DEFAULT_TAG_SPACING = 10 / / default distance between tags private static final int DEFAULT_FIXED_COLUMN_SIZE = 3; / / default number of columns 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.FlowTagViewFixed.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;// Line spacing private int mTagSpacing;// distance between tags 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) {/ / get attributes 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) {/ / Code required for fixed number of columns 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;} / * Click the listening interface * / public interface TagItemClickListener {void itemClick (int position);} class DataChangeObserver extends DataSetObserver {@ Override public void onChanged () {FlowTagView.this.drawLayout () } @ Override public void onInvalidated () {super.onInvalidated ();}
two。 Test class
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 List chooseList = 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 ("enthusiastic", "1"); Evaluate e2 = new Evaluate ("considerate service", "2"); Evaluate e3 = new Evaluate ("average", "3"); Evaluate e4 = new Evaluate ("technical leverage", "4") Evaluate e5 = new Evaluate ("professional proficiency", "5"); Evaluate e6 = new Evaluate ("only bragging", "6"); Evaluate e7 = new Evaluate ("Underground first only", "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.ischored; 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 List list; 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;}}
Layout file
Bg_round_corner_line_orange.xml
Bg_round_corner_line_gray.xml
At this point, I believe you have a deeper understanding of "how to customize View to achieve label flow effect in Android". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.