自定义控件:流式布局
生活随笔
收集整理的這篇文章主要介紹了
自定义控件:流式布局
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
實現代碼
public class FlowLayout extends ViewGroup {private List<Line> mLines = new ArrayList<Line>(); // 用來記錄描述有多少行Viewprivate Line mCurrrenLine; // 用來記錄當前已經添加到了哪一行private int mHorizontalSpace = 10;private int mVerticalSpace = 10;public FlowLayout(Context context, AttributeSet attrs) {super(context, attrs);}public FlowLayout(Context context) {super(context);}public void setSpace(int horizontalSpace, int verticalSpace) {this.mHorizontalSpace = horizontalSpace;this.mVerticalSpace = verticalSpace;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// 清空mLines.clear();mCurrrenLine = null;int layoutWidth = MeasureSpec.getSize(widthMeasureSpec);// 獲取行最大的寬度int maxLineWidth = layoutWidth - getPaddingLeft() - getPaddingRight();// 測量孩子int count = getChildCount();for (int i = 0; i < count; i++) {View view = getChildAt(i);// 如果孩子不可見if (view.getVisibility() == View.GONE) {continue;}// 測量孩子measureChild(view, widthMeasureSpec, heightMeasureSpec);// 往lines添加孩子if (mCurrrenLine == null) {// 說明還沒有開始添加孩子mCurrrenLine = new Line(maxLineWidth, mHorizontalSpace);// 添加到 Lines中mLines.add(mCurrrenLine);// 行中一個孩子都沒有mCurrrenLine.addView(view);} else {// 行不為空,行中有孩子了boolean canAdd = mCurrrenLine.canAdd(view);if (canAdd) {// 可以添加mCurrrenLine.addView(view);} else {// 不可以添加,裝不下去// 換行// 新建行mCurrrenLine = new Line(maxLineWidth, mHorizontalSpace);// 添加到lines中mLines.add(mCurrrenLine);// 將view添加到linemCurrrenLine.addView(view);}}}// 設置自己的寬度和高度int measuredWidth = layoutWidth;// paddingTop + paddingBottom + 所有的行間距 + 所有的行的高度float allHeight = 0;for (int i = 0; i < mLines.size(); i++) {float mHeigth = mLines.get(i).mHeigth;// 加行高allHeight += mHeigth;// 加間距if (i != 0) {allHeight += mVerticalSpace;}}int measuredHeight = (int) (allHeight + getPaddingTop() + getPaddingBottom() + 0.5f);setMeasuredDimension(measuredWidth, measuredHeight);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {// 給Child 布局---> 給Line布局int paddingLeft = getPaddingLeft();int offsetTop = getPaddingTop();for (int i = 0; i < mLines.size(); i++) {Line line = mLines.get(i);// 給行布局line.layout(paddingLeft, offsetTop);offsetTop += line.mHeigth + mVerticalSpace;}}class Line {private List<View> mViews = new ArrayList<View>(); // 用來記錄每一行有幾個Viewprivate float mMaxWidth; // 行最大的寬度private float mUsedWidth; // 已經使用了多少寬度private float mHeigth; // 行的高度private float mMarginLeft;private float mMarginRight;private float mMarginTop;private float mMarginBottom;private float mHorizontalSpace; // View和view之間的水平間距public Line(int maxWidth, int horizontalSpace) {this.mMaxWidth = maxWidth;this.mHorizontalSpace = horizontalSpace;}/*** 添加view,記錄屬性的變化* @param view*/public void addView(View view) {// 加載View的方法int size = mViews.size();int viewWidth = view.getMeasuredWidth();int viewHeight = view.getMeasuredHeight();// 計算寬和高if (size == 0) {// 說還沒有添加Viewif (viewWidth > mMaxWidth) {mUsedWidth = mMaxWidth;} else {mUsedWidth = viewWidth;}mHeigth = viewHeight;} else {// 多個view的情況mUsedWidth += viewWidth + mHorizontalSpace;mHeigth = mHeigth < viewHeight ? viewHeight : mHeigth;}// 將View記錄到集合中mViews.add(view);}/*** 用來判斷是否可以將View添加到line中* @param view* @return*/public boolean canAdd(View view) {// 判斷是否能添加Viewint size = mViews.size();if (size == 0) {return true;}int viewWidth = view.getMeasuredWidth();// 預計使用的寬度float planWidth = mUsedWidth + mHorizontalSpace + viewWidth;if (planWidth > mMaxWidth) {// 加不進去return false;}return true;}/*** 給孩子布局* @param offsetLeft* @param offsetTop*/public void layout(int offsetLeft, int offsetTop) {// 給孩子布局int currentLeft = offsetLeft;int size = mViews.size();// 判斷已經使用的寬度是否小于最大的寬度float extra = 0;float widthAvg = 0;if (mMaxWidth > mUsedWidth) {extra = mMaxWidth - mUsedWidth;widthAvg = extra / size;}for (int i = 0; i < size; i++) {View view = mViews.get(i);int viewWidth = view.getMeasuredWidth();int viewHeight = view.getMeasuredHeight();// 判斷是否有富余if (widthAvg != 0) {// 改變寬度,View的長度改變了,需要重新measureint newWidth = (int) (viewWidth + widthAvg + 0.5f);int widthMeasureSpec = MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.EXACTLY);int heightMeasureSpec = MeasureSpec.makeMeasureSpec(viewHeight, MeasureSpec.EXACTLY);view.measure(widthMeasureSpec, heightMeasureSpec);viewWidth = view.getMeasuredWidth();viewHeight = view.getMeasuredHeight();}// 布局int left = currentLeft;int top = (int) (offsetTop + (mHeigth - viewHeight) / 2 + 0.5f);// int top = offsetTop;int right = left + viewWidth;int bottom = top + viewHeight;view.layout(left, top, right, bottom);currentLeft += viewWidth + mHorizontalSpace;}}}} public class FlowActivity extends AppCompatActivity {private ScrollView mScrollView;private FlowLayout mFlowLayout;private List<String> mData;private Gson mGson;private String appname = "['QQ','視頻','京東','youni有你','萬年歷-農歷黃歷','支付寶錢包']";@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);initData();initView();}private void initData() {mGson = new Gson();mData = mGson.fromJson(appname,new TypeToken<List<String>>(){}.getType());}private void initView() {setContentView(mScrollView = new ScrollView(this));SpannableString title = new SpannableString("流式布局,熱門標簽");title.setSpan(new ForegroundColorSpan(Color.WHITE),0,title.length(),Spannable.SPAN_INCLUSIVE_EXCLUSIVE);ActionBar actionBar = getSupportActionBar();actionBar.setTitle(title);mScrollView.setBackgroundColor(Color.parseColor("#eaeaea"));mScrollView.setVerticalScrollBarEnabled(false);mFlowLayout = new FlowLayout(this);int padding = UIUtil.dip2px(15);mFlowLayout.setPadding(UIUtil.dip2px(10), padding, UIUtil.dip2px(10), padding);mFlowLayout.setSpace(UIUtil.dip2px(10), UIUtil.dip2px(15));for (final String data : mData) {TextView textView = new TextView(this);int tvPadding = UIUtil.dip2px(10);textView.setPadding(UIUtil.dip2px(15), tvPadding, UIUtil.dip2px(15), tvPadding);textView.setGravity(Gravity.CENTER);textView.setTextSize(16);textView.setText(data);textView.setTextColor(Color.WHITE);Random random = new Random();//Math.random()int alpha = 255;int green = random.nextInt(190) + 30;int red = random.nextInt(190) + 30;int blue = random.nextInt(190) + 30;int argb = Color.argb(alpha, red, green, blue);//設置shapeGradientDrawable normalDrawable = new GradientDrawable();normalDrawable.setCornerRadius(UIUtil.dip2px(6));normalDrawable.setColor(argb);GradientDrawable pressedDrawable = new GradientDrawable();pressedDrawable.setColor(Color.DKGRAY);pressedDrawable.setCornerRadius(UIUtil.dip2px(5));//設置選擇器selectorStateListDrawable stateListDrawable = new StateListDrawable();stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, pressedDrawable);stateListDrawable.addState(new int[]{}, normalDrawable);textView.setBackgroundDrawable(stateListDrawable);textView.setClickable(true);textView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {ToastUtil.toast(data);}});mFlowLayout.addView(textView);}mScrollView.addView(mFlowLayout);} }總結
以上是生活随笔為你收集整理的自定义控件:流式布局的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 自定义控件:水波纹
- 下一篇: Android开发工具:Git,Gith