Android中怎么自定义View实现标签流效果
本篇内容主要讲解“Android中怎么自定义View实现标签流效果”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Android中怎么自定义View实现标签流效果”吧!
一、概述Android自定义View实现标签流效果,一行放不下时会自动换行,用户可以自己定义单个标签的样式,可以选中和取消,可以监听单个标签的点击事件,功能还算强大,可以满足大部分开发需求,值得推荐,效果图如下:
二、实现代码1.自定义View
定义属性文件
<declare-styleablename="FlowTagView"><attrname="lineSpacing"format="dimension"/><attrname="tagSpacing"format="dimension"/><!--是否是固定布局--><attrname="isFixed"format="boolean"/><attrname="columnSize"format="integer"/></declare-styleable>
FlowTagConfig.java
packagecom.czhappy.effectdemo.flowtag;importandroid.content.Context;importandroid.content.res.TypedArray;importandroid.util.AttributeSet;importcom.czhappy.effectdemo.R;/***Description:*User:chenzheng*Date:2017/2/170017*Time:10:23*/publicclassFlowTagConfig{privatestaticfinalintDEFAULT_LINE_SPACING=5;//默认行间距privatestaticfinalintDEFAULT_TAG_SPACING=10;//各个标签之间的默认距离privatestaticfinalintDEFAULT_FIXED_COLUMN_SIZE=3;//默认列数privateintlineSpacing;privateinttagSpacing;privateintcolumnSize;privatebooleanisFixed;publicFlowTagConfig(Contextcontext,AttributeSetattrs){TypedArraya=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();}}publicintgetLineSpacing(){returnlineSpacing;}publicvoidsetLineSpacing(intlineSpacing){this.lineSpacing=lineSpacing;}publicintgetTagSpacing(){returntagSpacing;}publicvoidsetTagSpacing(inttagSpacing){this.tagSpacing=tagSpacing;}publicintgetColumnSize(){returncolumnSize;}publicvoidsetColumnSize(intcolumnSize){this.columnSize=columnSize;}publicbooleanisFixed(){returnisFixed;}publicvoidsetIsFixed(booleanisFixed){this.isFixed=isFixed;}}
FlowTagView.java
packagecom.czhappy.effectdemo.flowtag;importandroid.content.Context;importandroid.database.DataSetObserver;importandroid.graphics.Canvas;importandroid.util.AttributeSet;importandroid.view.View;importandroid.view.ViewGroup;importandroid.widget.BaseAdapter;/***Description:*User:chenzheng*Date:2017/2/170017*Time:10:23*/publicclassFlowTagViewextendsViewGroup{privateintmLineSpacing;//行间距privateintmTagSpacing;//各个标签之间的距离privateBaseAdaptermAdapter;privateTagItemClickListenermListener;privateDataChangeObservermObserver;publicFlowTagView(Contextcontext){super(context);init(context,null,0);}publicFlowTagView(Contextcontext,AttributeSetattrs){super(context,attrs);init(context,attrs,0);}publicFlowTagView(Contextcontext,AttributeSetattrs,intdefStyle){super(context,attrs,defStyle);init(context,attrs,defStyle);}privatevoidinit(Contextcontext,AttributeSetattrs,intdefStyle){//获取属性FlowTagConfigconfig=newFlowTagConfig(context,attrs);mLineSpacing=config.getLineSpacing();mTagSpacing=config.getTagSpacing();}privatevoiddrawLayout(){if(mAdapter==null||mAdapter.getCount()==0){return;}this.removeAllViews();for(inti=0;i<mAdapter.getCount();i++){Viewview=mAdapter.getView(i,null,null);finalintposition=i;view.setOnClickListener(newOnClickListener(){@OverridepublicvoidonClick(Viewv){if(mListener!=null){mListener.itemClick(position);}}});this.addView(view);}}@OverrideprotectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){intwantHeight=0;intwantWidth=resolveSize(0,widthMeasureSpec);intpaddingLeft=getPaddingLeft();intpaddingRight=getPaddingRight();intpaddingTop=getPaddingTop();intpaddingBottom=getPaddingBottom();intchildLeft=paddingLeft;intchildTop=paddingTop;intlineHeight=0;//固定列的数量所需要的代码for(inti=0;i<getChildCount();i++){finalViewchildView=getChildAt(i);LayoutParamsparams=childView.getLayoutParams();childView.measure(getChildMeasureSpec(widthMeasureSpec,paddingLeft+paddingRight,params.width),getChildMeasureSpec(heightMeasureSpec,paddingTop+paddingBottom,params.height));//获取单个tag的宽高intchildHeight=childView.getMeasuredHeight();intchildWidth=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));}@OverrideprotectedvoidonLayout(booleanchanged,intl,intt,intr,intb){//固定列的数量所需要的代码intwidth=r-l;intpaddingLeft=getPaddingLeft();intpaddingTop=getPaddingTop();intpaddingRight=getPaddingRight();intchildLeft=paddingLeft;intchildTop=paddingTop;intlineHeight=0;for(inti=0;i<getChildCount();i++){finalViewchildView=getChildAt(i);if(childView.getVisibility()==View.GONE){continue;}intchildWidth=childView.getMeasuredWidth();intchildHeight=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;}}@OverrideprotectedvoidonDraw(Canvascanvas){super.onDraw(canvas);}@OverridepublicLayoutParamsgenerateLayoutParams(AttributeSetattrs){returnnewLayoutParams(this.getContext(),attrs);}publicvoidsetAdapter(BaseAdapteradapter){if(mAdapter==null){mAdapter=adapter;if(mObserver==null){mObserver=newDataChangeObserver();mAdapter.registerDataSetObserver(mObserver);}drawLayout();}}publicvoidsetItemClickListener(TagItemClickListenermListener){this.mListener=mListener;}/***单击监听接口*/publicinterfaceTagItemClickListener{voiditemClick(intposition);}classDataChangeObserverextendsDataSetObserver{@OverridepublicvoidonChanged(){FlowTagView.this.drawLayout();}@OverridepublicvoidonInvalidated(){super.onInvalidated();}}}
2.测试类
FlowTagActivity.java
packagecom.czhappy.effectdemo.activity;importandroid.os.Bundle;importandroid.support.annotation.Nullable;importandroid.support.v7.app.AppCompatActivity;importcom.czhappy.effectdemo.R;importcom.czhappy.effectdemo.adapter.EvaluateAdapter;importcom.czhappy.effectdemo.flowtag.FlowTagView;importcom.czhappy.effectdemo.model.Evaluate;importjava.util.ArrayList;importjava.util.List;/***Description:*User:chenzheng*Date:2017/2/170017*Time:11:47*/publicclassFlowTagActivityextendsAppCompatActivity{privateFlowTagViewmContainer;privateEvaluateAdapteradapter;privateList<Evaluate>chooseList=newArrayList<Evaluate>();@OverrideprotectedvoidonCreate(@NullableBundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_flowtag);initView();initData();}privatevoidinitData(){List<Evaluate>list=newArrayList();Evaluatee1=newEvaluate("热情","1");Evaluatee2=newEvaluate("服务周到","2");Evaluatee3=newEvaluate("一般","3");Evaluatee4=newEvaluate("技术活杠杠的","4");Evaluatee5=newEvaluate("专业精通","5");Evaluatee6=newEvaluate("只会吹牛逼","6");Evaluatee7=newEvaluate("地下第一仅此一家","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);}privatevoidinitView(){mContainer=(FlowTagView)this.findViewById(R.id.container);adapter=newEvaluateAdapter(this);mContainer.setAdapter(adapter);mContainer.setItemClickListener(newFlowTagView.TagItemClickListener(){@OverridepublicvoiditemClick(intposition){Evaluatee=(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
packagecom.czhappy.effectdemo.adapter;importandroid.content.Context;importandroid.view.LayoutInflater;importandroid.view.View;importandroid.view.ViewGroup;importandroid.widget.BaseAdapter;importandroid.widget.TextView;importcom.czhappy.effectdemo.R;importcom.czhappy.effectdemo.model.Evaluate;importjava.util.ArrayList;importjava.util.List;/***Description:*User:chenzheng*Date:2017/2/170017*Time:11:43*/publicclassEvaluateAdapterextendsBaseAdapter{privateContextcontext;privateLayoutInflatermInflater;privateList<Evaluate>list;publicEvaluateAdapter(Contextcontext){this.context=context;this.mInflater=LayoutInflater.from(context);this.list=newArrayList<Evaluate>();}publicList<Evaluate>getList(){returnlist;}publicvoidsetItems(List<Evaluate>list){this.list=list;notifyDataSetChanged();}@OverridepublicintgetCount(){returnlist==null?0:list.size();}@OverridepublicObjectgetItem(intposition){returnlist.get(position);}@OverridepubliclonggetItemId(intposition){//TODOAuto-generatedmethodstubreturn0;}@OverridepublicViewgetView(intposition,ViewconvertView,ViewGroupparent){ViewHolderholder=null;if(convertView==null){holder=newViewHolder();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();}finalEvaluateee=(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);}returnconvertView;}privatefinalclassViewHolder{privateTextViewevaluate_tv;}}
布局文件
<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns: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.FlowTagViewandroid: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
<?xmlversion="1.0"encoding="utf-8"?><shapexmlns:android="http://schemas.android.com/apk/res/android"><solidandroid:color="#ffffff"/><cornersandroid:radius="5dp"/><strokeandroid:width="0.5dp"android:color="#FF6700"/></shape>
bg_round_corner_line_gray.xml
<?xmlversion="1.0"encoding="utf-8"?><shapexmlns:android="http://schemas.android.com/apk/res/android"><solidandroid:color="#ffffff"/><cornersandroid:radius="5dp"/><strokeandroid:width="0.5dp"android:color="#cccccc"/></shape>
到此,相信大家对“Android中怎么自定义View实现标签流效果”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。