zoukankan      html  css  js  c++  java
  • Android初级教程_获取Android控件的宽和高

    转载:http://blog.csdn.net/johnny901114/article/details/7839512

    我们都知道在onCreate()里面获取控件的高度是0,这是为什么呢?我们来看一下示例:

    首先我们自己写一个控件,这个控件非常简单:

    public class MyImageView extends ImageView {
    
        public MyImageView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
        public MyImageView(Context context) {
            super(context);
        }
        
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            System.out.println("onMeasure 我被调用了"+System.currentTimeMillis());
        }
        
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            System.out.println("onDraw 我被调用了"+System.currentTimeMillis());
        }
    
    }

    布局文件:

    <com.test.MyImageView
            android:id="@+id/imageview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/test" />

    测试的Activity的onCreate():

    @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);        
            System.out.println("执行完毕.."+System.currentTimeMillis());
        }

    现在我们现在来看一下结果:

      

    说明等onCreate方法执行完了,我们定义的控件才会被度量(measure),所以我们在onCreate方法里面通过view.getHeight()获取控件的高度或者宽度肯定是0,因为它自己还没有被度量,也就是说他自己都不知道自己有多高,而你这时候去获取它的尺寸,肯定是不行的.

    现在碰到这个问题我们不能不解决,在网上找到了如下办法:

    //------------------------------------------------方法一
            int w = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
            int h = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
            imageView.measure(w, h);
            int height =imageView.getMeasuredHeight();
            int width =imageView.getMeasuredWidth();
            textView.append("
    "+height+","+width);
            
            
            
    
            //-----------------------------------------------方法二
            ViewTreeObserver vto = imageView.getViewTreeObserver();
            vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                public boolean onPreDraw() {
                    int height = imageView.getMeasuredHeight();
                    int width = imageView.getMeasuredWidth();
                    textView.append("
    "+height+","+width);
                    return true;
                }
            });
            //-----------------------------------------------方法三   
            ViewTreeObserver vto2 = imageView.getViewTreeObserver();  
            vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
                @Override  
                public void onGlobalLayout() {
                    imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);  
                    textView.append("
    
    "+imageView.getHeight()+","+imageView.getWidth());
                }  
            });  

    这三个方法是哪里找到现在已经忘了.

    现在要讨论的是当我们需要时候使用哪个方法呢?

    现在把测试的Activity改成如下:

    @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            final ImageView imageView = (ImageView) findViewById(R.id.imageview);      
            
            //------------------------------------------------方法一
            int w = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
            int h = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);
            imageView.measure(w, h);
            int height =imageView.getMeasuredHeight();
            int width =imageView.getMeasuredWidth();
            textView.append("
    "+height+","+width);
            
            System.out.println("执行完毕.."+System.currentTimeMillis());
        }

      

    接着来看下面几种方式输出结果:

    把测试Activity改成如下:

    @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            final ImageView imageView = (ImageView) findViewById(R.id.imageview);
            //-----------------------------------------------方法二
            ViewTreeObserver vto = imageView.getViewTreeObserver();
            vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                public boolean onPreDraw() {
                    int height = imageView.getMeasuredHeight();
                    int width = imageView.getMeasuredWidth();
                    textView.append("
    "+height+","+width);
                    return true;
                }
            });
        }

    结果如下:

      

    方法三就不再测试了同方法二!!!

    那么方法而和方法三在执行上有什么区别呢?

    我们在布局文件中加入一个TextView来记录这个控件的宽高.

    <ScrollView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >
    
            <TextView
                android:id="@+id/text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
        </ScrollView>

    先来测试方法而:

    @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            final ImageView imageView = (ImageView) findViewById(R.id.imageview);
            //-----------------------------------------------方法二
            ViewTreeObserver vto = imageView.getViewTreeObserver();
            vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                public boolean onPreDraw() {
                    int height = imageView.getMeasuredHeight();
                    int width = imageView.getMeasuredWidth();
                    textView.append("
    "+height+","+width);
                    return true;
                }
            });
        }

    结果如下:

      

    我们再来测试方法三

    @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            final ImageView imageView = (ImageView) findViewById(R.id.imageview);
            //-----------------------------------------------方法三   
            ViewTreeObserver vto2 = imageView.getViewTreeObserver();  
            vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
                @Override  
                public void onGlobalLayout() {
                    imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);  
                    textView.append("
    
    "+imageView.getHeight()+","+imageView.getWidth());
                }  
            });  
        }

    输出结果如下:

      

    我想这方法二和方法三之间的区别就不用说了吧.

      总结:那么需要获取控件的宽高该用那个方法呢?

    方法一: 比其他的两个方法多了一次计算,也就是多调用了一次onMeasure()方法,该方法虽然看上去简单,但是如果要目标控件计算耗时比较大的话(如listView等),不建议使用.

    方法二,它的回调方法会调用很多次,并且滑动TextView的时候任然会调用,所以不建议使用.

    方法三,比较合适.

    当然,实际应用的时候需要根据实际情况而定.

  • 相关阅读:
    [译] 我最终是怎么玩转了 Vue 的作用域插槽
    通俗易懂的Git使用入门教程
    JS取出两个数组的不同或相同元素
    jQuery中四种事件监听的区别
    vuex里mapState,mapGetters使用详解
    php 获取时间今天明天昨天时间戳
    Linux crontab定时执行任务
    php返回json数据函数实例_php技巧_脚本之家
    mysql查看表结构命令
    Mysql命令大全
  • 原文地址:https://www.cnblogs.com/AndroidJotting/p/5279803.html
Copyright © 2011-2022 走看看