zoukankan      html  css  js  c++  java
  • Android自定义组件之自动换行及宽度自适应View:WordWrapView

    目的:

    自定义一个ViewGroup,里面的子view都是TextView,每个子view  TextView的宽度随内容自适应且每行的子View的个数自适应,并可以自动换行

    一:效果图

    二:代码

    整个代码不是很多,注释都在代码中,比较简单,一般都可以看懂。

    2.1:自定义属性

     目录:res/values/styles.xml

        <declare-styleable name="WordWrapView">
            <attr name="padding_hor" format="dimension"/>
            <attr name="padding_vertical" format="dimension"/>
            <attr name="margin_hor" format="dimension"/>
            <attr name="margin_vertial" format="dimension"/>
        </declare-styleable>

    2.1:WordWrapView代码

    public class WordWrapView extends ViewGroup {
    
        private  int padding_hor =10;//子view水平方向padding
        private  int padding_vertical=10;//子view垂直方向padding
        private  int margin_hor=20;//子view之间的水平间距
        private  int margin_vertical=20;//行间距
    
      
        private int num = 0;//最多字个数  
      
        /** 
         * @param context 
         */  
        public WordWrapView(Context context) {
            super(context);
        }
    
        /**
         * @param context
         * @param attrs
         */
        public WordWrapView(Context context, AttributeSet attrs) {
            super(context, attrs);
            initAttrs(context,attrs);
        }
    
        /**
         * @param context
         * @param attrs
         * @param defStyle
         */
        public WordWrapView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            initAttrs(context,attrs);
        }
    
        //获取属性值
        private void initAttrs(Context context, AttributeSet attrs) {
            TypedArray ta=context.obtainStyledAttributes(attrs,R.styleable.WordWrapView);
            padding_hor= (int) ta.getDimension(R.styleable.WordWrapView_padding_hor,10);
            padding_vertical= (int) ta.getDimension(R.styleable.WordWrapView_padding_vertical,10);
            margin_hor= (int) ta.getDimension(R.styleable.WordWrapView_margin_hor,20);
            margin_vertical= (int) ta.getDimension(R.styleable.WordWrapView_margin_vertial,20);
            ta.recycle();
        }
    
    
      
        @Override  
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            int childCount=getChildCount();
            int acturalWith=r-l;//实际宽度
            int x=0;
            int y=0;
            int rows=1;
    
            for (int i = 0; i <childCount ; i++) {//判断累积高度
                View view=getChildAt(i);
                int width=view.getMeasuredWidth();
                int height=view.getMeasuredHeight();
                x+=width+margin_hor;
                if(x>acturalWith-margin_hor){
                    if(i!=0){
                        x=width+margin_hor;
                        rows++;
                    }
                }
                //当一个子view长度超出父view长度时
                if(x>acturalWith-margin_hor){
                    if(view instanceof TextView){//判断单个高度
                        TextView tv= (TextView) view;
                        if(num==0){
                            int wordNum=tv.getText().toString().length();
                            num=wordNum*(acturalWith-2*margin_hor-2* padding_hor)/(width-2* padding_hor)-1;
                        }
                        String text=tv.getText().toString();
                        text=text.substring(0,num)+"...";
                        tv.setText(text);
                    }
                    x=acturalWith-margin_hor;
                    width=acturalWith-2*margin_hor;
                }
    
    
                y = rows * (height + margin_vertical);
                view.layout(x - width, y - height, x, y);
            }
        }  
      
        public float getCharacterWidth(String text, float size) {  
            if (null == text || "".equals(text))  
                return 0;  
            float width = 0;  
            Paint paint = new Paint();
            paint.setTextSize(size);  
            float text_width = paint.measureText(text);// 得到总体长度  
            width = text_width / text.length();// 每一个字符的长度  
      
            return width;  
        }  
      
        @Override  
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int x=0;//横坐标
            int y=0;//纵坐标
            int rows=1;//总行数
            int specWidth=MeasureSpec.getSize(widthMeasureSpec);
            int acturalWith=specWidth;//实际宽度
            int childCount=getChildCount();
            for (int i = 0; i <childCount ; i++) {
                View child=getChildAt(i);
                child.setPadding(padding_hor,padding_vertical, padding_hor,padding_vertical);
                child.measure(MeasureSpec.UNSPECIFIED,MeasureSpec.UNSPECIFIED);
                int width=child.getMeasuredWidth();
                int height=child.getMeasuredHeight();
                x+=width+margin_hor;
                if(x>acturalWith-margin_hor){//换行
                    if(i!=0){
                        x=width+margin_hor;
                        rows++;
                    }
                }
                y=rows*(height+margin_vertical);
            }
            setMeasuredDimension(acturalWith,y+margin_vertical);
        }
    
        public int getPadding_hor() {
            return padding_hor;
        }
    
        public void setPadding_hor(int padding_hor) {
            this.padding_hor = padding_hor;
        }
    
        public int getPadding_vertical() {
            return padding_vertical;
        }
    
        public void setPadding_vertical(int padding_vertical) {
            this.padding_vertical = padding_vertical;
        }
    
        public int getMargin_hor() {
            return margin_hor;
        }
    
        public void setMargin_hor(int margin_hor) {
            this.margin_hor = margin_hor;
        }
    
        public int getMargin_vertical() {
            return margin_vertical;
        }
    
        public void setMargin_vertical(int margin_vertical) {
            this.margin_vertical = margin_vertical;
        }
    }
    

      

    2.3:布局文件中使用

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
        <com.example.custiomview1.UI.WordWrapView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/wordWrapView"
            app:margin_hor="10dp"
            app:padding_vertical="5dp"
            ></com.example.custiomview1.UI.WordWrapView>
        
    </RelativeLayout>
    

      

    2.4:Avtivity中使用

    public class MainActivity extends AppCompatActivity {
        private WordWrapView wordWrapView;
        private String[] strs = new String[] { "哲学系", "新疆维吾尔自治区新疆维吾尔自治区新疆维吾尔自治区新疆维吾尔自治区新疆维吾尔自治区",
                "新闻学", "心理学",
                "犯罪心理学", "明明白白新疆维吾尔自治区新疆维吾尔自治区新疆维吾尔自治区新疆维吾尔自治区新疆维吾尔自治区",
                "西方文学史", "计算机", "掌声", "心太软", "生命",
                "程序开发" };
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            wordWrapView=findViewById(R.id.wordWrapView);
            //添加子view:TextView
            for (String str : strs) {
                TextView tv=new TextView(MainActivity.this);
                tv.setTextSize(14);//设置字体大小
                tv.setTextColor(Color.WHITE);
                tv.setText(str);
                tv.setBackgroundResource(R.drawable.shape_bg);//子view背景
                wordWrapView.addView(tv);
            }
        }
    }
    

      

    参考:【Android进阶】Android自定义组件之自动换行View,以TextView为例

  • 相关阅读:
    docker学习
    redis哨兵部署
    HUE中一些重要元数据表的DDL整理
    Autosys中ON_HOLD和ON_ICE的区别
    Spark结构化API的执行过程——Logical Plan & Physical Plan
    关于Spark中Columns的引用方法
    关于Spark Dataset API中的Typed transformations和Untyped transformations
    关于Kafka Consumer 与 Partitions
    使用sed根据变量值注释掉文件中相匹配的记录行
    sqoop export to teradata时出现java.lang.NullPointerException
  • 原文地址:https://www.cnblogs.com/wangjiaghe/p/9062147.html
Copyright © 2011-2022 走看看