• android 自己定义ViewGroup实现可记载并呈现选择的ListView


    转载请注明出处:王亟亟的大牛之路

    之前也做过一些用TextView之类的记录ListView选项的东西。可是总认为好难看。发现个不错的实现就贴给大家。

    项目文件夹
    这里写图片描写叙述
    执行效果:
    这里写图片描写叙述

    自己定义视图:

    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    public class FlowLayout extends ViewGroup {
    
        private int mGravity = (isIcs() ? Gravity.START : Gravity.LEFT) | Gravity.TOP;
    
        private final List<List<View>> mLines = new ArrayList<List<View>>();
        private final List<Integer> mLineHeights = new ArrayList<Integer>();
        private final List<Integer> mLineMargins = new ArrayList<Integer>();
    
        public FlowLayout(Context context) {
            this(context, null);
        }
    
        public FlowLayout(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public FlowLayout(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
    
            TypedArray a = context.obtainStyledAttributes(attrs,
                    R.styleable.FlowLayout, defStyle, 0);
    
            try {
                int index = a.getInt(R.styleable.FlowLayout_android_gravity, -1);
                if(index > 0) {
                    setGravity(index);
                }
            } finally {
                a.recycle();
            }
    
        }
    
        /**
         * {@inheritDoc}
         */
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
            int sizeWidth = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
            int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
    
            int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
            int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
    
            int width = 0;
            int height = getPaddingTop() + getPaddingBottom();
    
            int lineWidth = 0;
            int lineHeight = 0;
    
            int childCount = getChildCount();
    
            for(int i = 0; i < childCount; i++) {
    
                View child = getChildAt(i);
                boolean lastChild = i == childCount - 1;
    
                if(child.getVisibility() == View.GONE) {
    
                    if(lastChild) {
                        width = Math.max(width, lineWidth);
                        height += lineHeight;
                    }
    
                    continue;
                }
    
                measureChildWithMargins(child, widthMeasureSpec, lineWidth, heightMeasureSpec, height);
    
                LayoutParams lp = (LayoutParams) child.getLayoutParams();
    
                int childWidthMode = MeasureSpec.AT_MOST;
                int childWidthSize = sizeWidth;
    
                int childHeightMode = MeasureSpec.AT_MOST;
                int childHeightSize = sizeHeight;
    
                if(lp.width == LayoutParams.MATCH_PARENT) {
                    childWidthMode = MeasureSpec.EXACTLY    ;
                    childWidthSize -= lp.leftMargin + lp.rightMargin;
                } else if(lp.width >= 0) {
                    childWidthMode = MeasureSpec.EXACTLY;
                    childWidthSize = lp.width;
                }
    
                if(lp.height >= 0) {
                    childHeightMode = MeasureSpec.EXACTLY;
                    childHeightSize = lp.height;
                } else if (modeHeight == MeasureSpec.UNSPECIFIED) {
                    childHeightMode = MeasureSpec.UNSPECIFIED;
                    childHeightSize = 0;
                }
    
                child.measure(
                        MeasureSpec.makeMeasureSpec(childWidthSize, childWidthMode),
                        MeasureSpec.makeMeasureSpec(childHeightSize, childHeightMode)
                );
    
                int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
    
                if(lineWidth + childWidth > sizeWidth) {
    
                    width = Math.max(width, lineWidth);
                    lineWidth = childWidth;
    
                    height += lineHeight;
                    lineHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
    
                } else {
                    lineWidth += childWidth;
                    lineHeight = Math.max(lineHeight, child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
                }
    
                if(lastChild) {
                    width = Math.max(width, lineWidth);
                    height += lineHeight;
                }
    
            }
    
            width += getPaddingLeft() + getPaddingRight();
    
            setMeasuredDimension(
                    (modeWidth == MeasureSpec.EXACTLY) ? sizeWidth : width,
                    (modeHeight == MeasureSpec.EXACTLY) ? sizeHeight : height);
        }
    
        /**
         * {@inheritDoc}
         */
        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
    
            mLines.clear();
            mLineHeights.clear();
            mLineMargins.clear();
    
            int width = getWidth();
            int height = getHeight();
    
            int linesSum = getPaddingTop();
    
            int lineWidth = 0;
            int lineHeight = 0;
            List<View> lineViews = new ArrayList<View>();
    
            float horizontalGravityFactor;
            switch ((mGravity & Gravity.HORIZONTAL_GRAVITY_MASK)) {
                case Gravity.LEFT:
                default:
                    horizontalGravityFactor = 0;
                    break;
                case Gravity.CENTER_HORIZONTAL:
                    horizontalGravityFactor = .5f;
                    break;
                case Gravity.RIGHT:
                    horizontalGravityFactor = 1;
                    break;
            }
    
            for(int i = 0; i < getChildCount(); i++) {
    
                View child = getChildAt(i);
    
                if(child.getVisibility() == View.GONE) {
                    continue;
                }
    
                LayoutParams lp = (LayoutParams) child.getLayoutParams();
    
                int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
                int childHeight = child.getMeasuredHeight() + lp.bottomMargin + lp.topMargin;
    
                if(lineWidth + childWidth > width) {
                    mLineHeights.add(lineHeight);
                    mLines.add(lineViews);
                    mLineMargins.add((int) ((width - lineWidth) * horizontalGravityFactor) + getPaddingLeft());
    
                    linesSum += lineHeight;
    
                    lineHeight = 0;
                    lineWidth = 0;
                    lineViews = new ArrayList<View>();
                }
    
                lineWidth += childWidth;
                lineHeight = Math.max(lineHeight, childHeight);
                lineViews.add(child);
            }
    
            mLineHeights.add(lineHeight);
            mLines.add(lineViews);
            mLineMargins.add((int) ((width - lineWidth) * horizontalGravityFactor) + getPaddingLeft());
    
            linesSum += lineHeight;
    
            int verticalGravityMargin = 0;
            switch ((mGravity & Gravity.VERTICAL_GRAVITY_MASK)  ) {
                case Gravity.TOP:
                default:
                    break;
                case Gravity.CENTER_VERTICAL:
                    verticalGravityMargin = (height - linesSum) / 2;
                    break;
                case Gravity.BOTTOM:
                    verticalGravityMargin = height - linesSum;
                    break;
            }
    
            int numLines = mLines.size();
    
            int left;
            int top = getPaddingTop();
    
            for(int i = 0; i < numLines; i++) {
    
                lineHeight = mLineHeights.get(i);
                lineViews = mLines.get(i);
                left = mLineMargins.get(i);
    
                int children = lineViews.size();
    
                for(int j = 0; j < children; j++) {
    
                    View child = lineViews.get(j);
    
                    if(child.getVisibility() == View.GONE) {
                        continue;
                    }
    
                    LayoutParams lp = (LayoutParams) child.getLayoutParams();
    
                    // if height is match_parent we need to remeasure child to line height
                    if(lp.height == LayoutParams.MATCH_PARENT) {
                        int childWidthMode = MeasureSpec.AT_MOST;
                        int childWidthSize = lineWidth;
    
                        if(lp.width == LayoutParams.MATCH_PARENT) {
                            childWidthMode = MeasureSpec.EXACTLY;
                        } else if(lp.width >= 0) {
                            childWidthMode = MeasureSpec.EXACTLY;
                            childWidthSize = lp.width;
                        }
    
                        child.measure(
                                MeasureSpec.makeMeasureSpec(childWidthSize, childWidthMode),
                                MeasureSpec.makeMeasureSpec(lineHeight - lp.topMargin - lp.bottomMargin, MeasureSpec.EXACTLY)
                        );
                    }
    
                    int childWidth = child.getMeasuredWidth();
                    int childHeight = child.getMeasuredHeight();
    
                    int gravityMargin = 0;
    
                    if(Gravity.isVertical(lp.gravity)) {
                        switch (lp.gravity) {
                            case Gravity.TOP:
                            default:
                                break;
                            case Gravity.CENTER_VERTICAL:
                            case Gravity.CENTER:
                                gravityMargin = (lineHeight - childHeight - lp.topMargin - lp.bottomMargin) / 2 ;
                                break;
                            case Gravity.BOTTOM:
                                gravityMargin = lineHeight - childHeight - lp.topMargin - lp.bottomMargin;
                                break;
                        }
                    }
    
                    child.layout(left + lp.leftMargin,
                            top + lp.topMargin + gravityMargin + verticalGravityMargin,
                            left + childWidth + lp.leftMargin,
                            top + childHeight + lp.topMargin + gravityMargin + verticalGravityMargin);
    
                    left += childWidth + lp.leftMargin + lp.rightMargin;
    
                }
    
                top += lineHeight;
            }
    
        }
    
        @Override
        protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
            return new LayoutParams(p);
        }
    
        /**
         * {@inheritDoc}
         */
        @Override
        public LayoutParams generateLayoutParams(AttributeSet attrs) {
            return new LayoutParams(getContext(), attrs);
        }
    
        /**
         * {@inheritDoc}
         */
        @Override
        protected LayoutParams generateDefaultLayoutParams() {
            return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        }
    
        @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
        public void setGravity(int gravity) {
            if(mGravity != gravity) {
                if((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
                    gravity |= isIcs() ? Gravity.START : Gravity.LEFT;
                }
    
                if((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
                    gravity |= Gravity.TOP;
                }
    
                mGravity = gravity;
                requestLayout();
            }
        }
    
        public int getGravity() {
            return mGravity;
        }
    
        /**
         * @return <code>true</code> if device is running ICS or grater version of Android.
         */
        private static boolean isIcs() {
            return Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
        }
    
        public static class LayoutParams extends MarginLayoutParams {
    
            public int gravity = -1;
    
            public LayoutParams(Context c, AttributeSet attrs) {
                super(c, attrs);
    
                TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.FlowLayout_Layout);
    
                try {
                    gravity = a.getInt(R.styleable.FlowLayout_Layout_android_layout_gravity, -1);
                } finally {
                    a.recycle();
                }
            }
    
            public LayoutParams(int width, int height) {
                super(width, height);
            }
    
            public LayoutParams(ViewGroup.LayoutParams source) {
                super(source);
            }
    
        }
    
    }
    

    分析:

    这部分主要是呈现被选项的实现。伸手党能够无视

    对象:

    public class Filter_Object {
        public String mName ;
        public boolean mIsSelected ;
    }
    

    分析:填充是否被选,以及listView每一行的显示内容

    MainActivity:

    public class MainActivity extends AppCompatActivity {
        private ListView mListView;
        private ArrayList<Filter_Object> mArrFilter;
        private ScrollView mScrollViewFilter;
        private Filter_Adapter mFilter_Adapter ;
        private FlowLayout mFlowLayoutFilter ;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    
                getWindow().setStatusBarColor(getResources().getColor(R.color.themecolor));
            }
    
            mArrFilter = new ArrayList<>();
    
            String[] strArr = getResources().getStringArray(R.array.city);
    
            int lengthOfstrArr = strArr.length;
    
            for (int i = 0; i < lengthOfstrArr; i++) {
                Filter_Object filter_object = new Filter_Object();
                filter_object.mName = strArr[i];
                filter_object.mIsSelected = false;
                mArrFilter.add(filter_object);
            }
    
            getSupportActionBar().setDisplayShowTitleEnabled(true);
            getSupportActionBar().setTitle(getString(R.string.app_name));
    
            mListView = (ListView) findViewById(R.id.listViewFilter);
            mScrollViewFilter = (ScrollView)findViewById(R.id.scrollViewFilter);
            //放置被选项的布局
            mFlowLayoutFilter = (FlowLayout)findViewById(R.id.flowLayout);
    
            mFilter_Adapter = new Filter_Adapter(mArrFilter);
            mListView.setAdapter(mFilter_Adapter);
        }
        public void addFilterTag() {
            final ArrayList<Filter_Object> arrFilterSelected = new ArrayList<>();
    
            mFlowLayoutFilter.removeAllViews();
    
            int length = mArrFilter.size();
            boolean isSelected = false;
            for (int i = 0; i < length; i++) {
                Filter_Object fil = mArrFilter.get(i);
                if (fil.mIsSelected) {
                    isSelected = true;
                    arrFilterSelected.add(fil);
                }
            }
            if (isSelected) {
                mScrollViewFilter.setVisibility(View.VISIBLE);
            } else {
                mScrollViewFilter.setVisibility(View.GONE);
            }
            int size = arrFilterSelected.size();
            LayoutInflater layoutInflater = (LayoutInflater)
                    this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    
            for (int i = 0; i < size; i++) {
                View view = layoutInflater.inflate(R.layout.filter_tag_edit, null);
    
                TextView tv = (TextView) view.findViewById(R.id.tvTag);
                LinearLayout linClose = (LinearLayout) view.findViewById(R.id.linClose);
                final Filter_Object filter_object = arrFilterSelected.get(i);
                linClose.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        //showToast(filter_object.name);
    
    
                        int innerSize = mArrFilter.size();
                        for (int j = 0; j < innerSize; j++) {
                            Filter_Object mFilter_Object = mArrFilter.get(j);
                            if (mFilter_Object.mName.equalsIgnoreCase(filter_object.mName)) {
                                mFilter_Object.mIsSelected = false;
    
                            }
                        }
                        addFilterTag();
                        mFilter_Adapter.updateListView(mArrFilter);
                    }
                });
    
    
                tv.setText(filter_object.mName);
                int color = getResources().getColor(R.color.themecolor);
    
                View newView = view;
                newView.setBackgroundColor(color);
    
                FlowLayout.LayoutParams params = new FlowLayout.LayoutParams(FlowLayout.LayoutParams.WRAP_CONTENT, FlowLayout.LayoutParams.WRAP_CONTENT);
                params.rightMargin = 10;
                params.topMargin = 5;
                params.leftMargin = 10;
                params.bottomMargin = 5;
    
                newView.setLayoutParams(params);
    
                mFlowLayoutFilter.addView(newView);
            }
        }
    
        public class Filter_Adapter extends BaseAdapter {
            ArrayList<Filter_Object> arrMenu;
    
            public Filter_Adapter(ArrayList<Filter_Object> arrOptions) {
                this.arrMenu = arrOptions;
            }
    
            public void updateListView(ArrayList<Filter_Object> mArray) {
                this.arrMenu = mArray;
                notifyDataSetChanged();
            }
    
            @Override
            public int getCount() {
                return this.arrMenu.size();
            }
    
            @Override
            public Object getItem(int position) {
                return null;
            }
    
            @Override
            public long getItemId(int position) {
                return 0;
            }
    
            @Override
            public View getView(final int position, View convertView, ViewGroup parent) {
                ViewHolder viewHolder;
                if (convertView == null) {
                    convertView = getLayoutInflater().inflate(R.layout.filter_list_item, null);
                    viewHolder = new ViewHolder();
                    viewHolder.mTtvName = (TextView) convertView.findViewById(R.id.tvName);
                    viewHolder.mTvSelected = (TextView) convertView.findViewById(R.id.tvSelected);
                    convertView.setTag(viewHolder);
                } else {
                    viewHolder = (ViewHolder) convertView.getTag();
                }
                final Filter_Object mService_Object = arrMenu.get(position);
                viewHolder.mTtvName.setText(mService_Object.mName);
    
                if (mService_Object.mIsSelected) {
                    viewHolder.mTvSelected.setVisibility(View.VISIBLE);
                } else {
                    viewHolder.mTvSelected.setVisibility(View.INVISIBLE);
                }
                convertView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
    
                        mService_Object.mIsSelected = !mService_Object.mIsSelected;
                        mScrollViewFilter.setVisibility(View.VISIBLE);
    
                        addFilterTag();
                        notifyDataSetChanged();
                    }
                });
                return convertView;
            }
    
            public class ViewHolder {
                TextView mTtvName, mTvSelected;
    
            }
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            // getMenuInflater().inflate(R.menu.menu_main, menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
    
            //noinspection SimplifiableIfStatement
            if (id == R.id.action_settings) {
                return true;
            }
    
            return super.onOptionsItemSelected(item);
        }
    }

    分析:

    层次非常分明,从填充本地数据–>转加载ListView–>附加逻辑–>呈现。等流程思路非常清晰,可读性非常强。

    详细使用,能够看源代码。一目了然。
    源代码地址:http://yunpan.cn/cdbbFUd8rLFmJ 訪问password af07

  • 相关阅读:
    spring@Async注解实现异步方法调用
    mysql锁机制
    springboot启动时执行任务CommandLineRunner
    java-并发编程之fork/join框架
    mysql explain 执行计划详解
    mysql 时间相关sql , 按天、月、季度、年等条件进行查询
    swagger2 常用注解说明
    VirtualBox 安装CentOS虚拟机网卡配置
    RestFul是啥
    文本内文字字数过多,显示省略号
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/7119384.html
Copyright © 2020-2023  润新知