• 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为例

  • 相关阅读:
    CSRF 攻击
    PHP中HTTP_X_FORWARDED_FOR 和 REMOTE_ADDR的使用
    PHP PDO函数库详解
    STK基础
    opnet统计结果的采集模式——capture mode
    一个博客园代码高亮的方案
    博客园TinyMCE编辑器中插入的代码块使用HTML编辑器再编辑
    local statistics和global statistics的区别
    opnet的函数中FIN、FRET和FOUT
    福昕阅读器默认打开pdf文件视图大小
  • 原文地址:https://www.cnblogs.com/wangjiaghe/p/9062147.html
Copyright © 2020-2023  润新知