編輯:關於Android編程
[TOC]
剛好項目中要實現這個布局效果,做完後在這裡分享出來給大家學習~
1、單行多行切換顯示
2、單選和取消選擇
/** * * @author jhone * @time 2016/08/08 * */ public class LabelView extends ViewGroup{ private Context context; //當前是否是打開狀態 private boolean isOpen=false; //用來疊加每一行的view private List> mAllChildViews = new ArrayList
>(); //用來疊加每一行的高度 private List
mLineHeight = new ArrayList (); public LabelView(Context context) { this(context, null); // TODO Auto-generated constructor stub } public LabelView(Context context, AttributeSet attrs) { this(context, attrs, 0); // TODO Auto-generated constructor stub } public LabelView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.context=context; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub int sizeWidth = MeasureSpec.getSize(widthMeasureSpec); int modeWidth = MeasureSpec.getMode(widthMeasureSpec); int sizeHeight = MeasureSpec.getSize(heightMeasureSpec); int modeHeight = MeasureSpec.getMode(heightMeasureSpec); //記錄每行的最大寬度和高度 int width = 0; int height = 0; //記錄每行的寬度和高度 int lineWidth = 0; int lineHeight = 0; int childCount = getChildCount(); for(int i = 0;i < childCount; i ++){ View child = getChildAt(i); measureChild(child, widthMeasureSpec, heightMeasureSpec); MarginLayoutParams lp = (MarginLayoutParams)child.getLayoutParams(); int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; if (isOpen) { //當疊加的子view寬度大於行寬時進行換行 if(lineWidth + childWidth > sizeWidth){ //對比得到最大的寬度,最終最大的寬度可能用來設置為控件的寬度 width = Math.max(width, lineWidth); //重置lineWidth lineWidth = childWidth; //記錄行高 lineHeight = childHeight; height += lineHeight; }else{//不換行情況 //疊加行寬 lineWidth += childWidth; //得到最大行高 lineHeight = Math.max(lineHeight, childHeight); } //處理最後一行,因為上面的邏輯沒有算上最後一行的,這裡通過最後一個子view來做一次判斷,執行最後一行的高度與寬度疊加與對比 if(i == childCount -1){ width = Math.max(width, lineWidth); height += lineHeight; } }else{//只顯示第一行 if(lineWidth + childWidth > sizeWidth){ width = Math.max(width, lineWidth); height = lineHeight; break; }else{ lineWidth += childWidth; lineHeight = Math.max(lineHeight, childHeight); } } } setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth : width, modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // TODO Auto-generated method stub mAllChildViews.clear(); mLineHeight.clear(); //獲取當前ViewGroup的寬度 int width = getWidth(); int lineWidth = 0; int lineHeight = 0; //記錄當前行的view List lineViews = new ArrayList (); int childCount = getChildCount(); for(int i = 0;i < childCount; i ++){ View child = getChildAt(i); MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); int childWidth = child.getMeasuredWidth(); int childHeight = child.getMeasuredHeight(); //如果需要換行 if(childWidth + lineWidth + lp.leftMargin + lp.rightMargin > width){ //記錄LineHeight mLineHeight.add(lineHeight); //記錄當前行的Views mAllChildViews.add(lineViews); //重置行的寬高 lineWidth = 0; lineHeight = childHeight + lp.topMargin + lp.bottomMargin; lineViews = new ArrayList(); } lineWidth += childWidth + lp.leftMargin + lp.rightMargin; lineHeight = Math.max(lineHeight, childHeight + lp.topMargin + lp.bottomMargin); lineViews.add(child); } //處理最後一行 mLineHeight.add(lineHeight); mAllChildViews.add(lineViews); //設置子View的位置 int left = 0; int top = 0; //獲取行數 int lineCount = mAllChildViews.size(); for(int i = 0; i < lineCount; i ++){ //當前行的views和高度 lineViews = mAllChildViews.get(i); lineHeight = mLineHeight.get(i); for(int j = 0; j < lineViews.size(); j ++){ View child = lineViews.get(j); //判斷是否顯示 if(child.getVisibility() == View.GONE){ continue; } MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); int cLeft = left + lp.leftMargin; int cTop = top + lp.topMargin; int cRight = cLeft + child.getMeasuredWidth(); int cBottom = cTop + child.getMeasuredHeight(); //進行子View布局 child.layout(cLeft, cTop, cRight, cBottom); left += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; } left = 0; top += lineHeight; if (!isOpen) {//如果只顯示一行,就跳出 break; } } } @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { // TODO Auto-generated method stub return new MarginLayoutParams(getContext(), attrs); } //記錄點過的位置 private TextView mask; public void addLabels(ArrayList labels){ MarginLayoutParams lp = new MarginLayoutParams( LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT); int paddingTop = (int) ScreenUtils.dpToPxInt(context, 6); int paddingLeft = (int) ScreenUtils.dpToPxInt(context, 10); lp.leftMargin = (int) ScreenUtils.dpToPxInt(context, 4); lp.rightMargin = (int) ScreenUtils.dpToPxInt(context, 4); lp.topMargin = (int) ScreenUtils.dpToPxInt(context, 5); lp.bottomMargin = (int) ScreenUtils.dpToPxInt(context, 5); for (String label:labels) { TextView view = new TextView(context); view.setPadding(paddingLeft, paddingTop, paddingLeft, paddingTop); view.setText(label); view.setTextSize(12); view.setTextColor(Color.parseColor("#797671")); view.setBackgroundResource(R.drawable.bg_round_black_stroken); view.setLayoutParams(lp); view.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { // TODO Auto-generated method stub if (view==mask) {//如果當前是選中狀態,再次點擊取消選中狀態,並且回調參數返回null ((TextView)view).setTextColor(Color.parseColor("#797671")); ((TextView)view).setBackgroundResource(R.drawable.bg_round_black_stroken); mask=null; if (l!=null) { l.onLabelChange(null); } }else{//點擊取消上一個選中view,也就是說只能單選,多選邏輯也簡單,在這裡記錄後回調,這裡我就不實現 了 if (mask!=null) { mask.setTextColor(Color.parseColor("#797671")); mask.setBackgroundResource(R.drawable.bg_round_black_stroken); } ((TextView)view).setTextColor(Color.parseColor("#06BE6A")); ((TextView)view).setBackgroundResource(R.drawable.bg_round_green_stroken); mask=(TextView) view; if (l!=null) { l.onLabelChange((TextView)view); } } } }); addView(view,lp); } } private OnLabelChangeListener l; public void setOnLabelChangeListener(OnLabelChangeListener l){ this.l=l; } public interface OnLabelChangeListener{ void onLabelChange(TextView textView); } /** * 切換操作 */ public void toggle() { if (!isOpen) { isOpen = true; requestLayout(); } else { isOpen = false; requestLayout(); } } }
實現這個還是比較簡單的,注釋也算詳細吧,就不多講了~
下載必備的軟件包下載並安裝WebStorm7。WebStorm7目前的穩定版本是7.0.3。為什麼我們選擇WebStorm?因為它提供了許多功能,如JavaScript代
為什麼APK要瘦身。APK越大,在下載安裝過程中,他們耗費的流量會越多,安裝等待時間也會越長;對於產品本身,意味著下載轉化率會越低(因為競品中,用戶有更多機會選擇那個體驗
按照我一開始的打算,上面一篇文章應該是“Android動畫總結系列(5)——屬性動畫源碼分析”,不過屬性動畫源碼分析寫起來
.xml代碼如下: .java程序如下: package org.lxh.demo; import java.io.Byte