解决 1.view.Layout() 失效 2. getTop() . getLeft() getTop() getBottom() 返回值为0

实践是检验真理的唯一标准

问题缘由:自定义View开发的小伙伴,肯定会遇到。代码中onCreate() 方法中 ,直接调用view.layout()想要移动控件位置的时候,发现效果并没有达到预期的(控件一点都没有移动,尴尬),然而通过Value动画调用该方法的时候,是起作用的。why?why?。

ValueAnimator animator=ValueAnimator.ofInt(0,400);
        animator.setDuration(3000);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Integer value = (Integer) animation.getAnimatedValue();
                iv.layout(iv.getLeft(),value,iv.getRight(),value+iv.getHeight());
            }
        });
        animator.start();

 开始办案:value动画,只是起了一个返回数值的作用,控件位置移动最终还是通过 layout 方法。因此,能接受的解释就是,layout 的起作用肯定是在某一个时刻执行的(确定的是,oncreate()执行的时候,它肯定无效)。

验证:oncreate() 中,延时3秒执行 view.layout() ,果然是起作用的。

iv.postDelayed(new Runnable() {
            @Override
            public void run() {
                iv.layout(0,0,iv.getWidth(),iv.getHeight());
            }
        },3000);

 因此,onlayout能否有效,只是一个时机的问题。通过实验:当activity的布局,完全布局成功的以后,layout 才会有效。onGlobalLayout()方法,执行了3次,在最后一次执行完以后,才有效果。

  final int[] i = {0};
        iv.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Log.i("LHT","onGlobalLayout  "+i[0]);
                if(i[0] ==2){
                   iv.layout(0,0,iv.getWidth(),iv.getHeight());
                }
                i[0]++;
                Log.i("LHT","left "+iv.getLeft());
            }
        });

测试中,onGlobalLayout() 一共回调了3次,当在第三次 以后,onlayout()起作用。从而延深到 getTop() 等方法,在onCreate() ,获取到的值为0,这也是个时机的问题。

解决方法,可以view.post()  run方法中获取,或者 和上面一样 ,在 onGlobalyout() 方法中获取。

 

offsetLeftAndRight();
offsetTopAndBottom();   系统封装api  可以替代 layout()
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 两个手指进行缩放布局 实现两个手指进行缩放布局,可以使用Android系统自带的GestureDetector和ScaleGestureDetector类。具体实现步骤如下: 1)创建一个自定义的View,重写onTouchEvent方法,实现手势监听; 2)在View的构造方法中创建GestureDetector和ScaleGestureDetector对象; 3)在onTouchEvent方法中调用GestureDetector和ScaleGestureDetector的onTouchEvent方法,分别监听单击、长按、滑动和缩放手势; 4)在onScale方法中获取当前缩放因子,设置View的缩放比例。 示例代码如下: ``` public class MyView extends View { private GestureDetector mGestureDetector; private ScaleGestureDetector mScaleGestureDetector; private float mScaleFactor = 1.0f; public MyView(Context context) { super(context); mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onDown(MotionEvent e) { return true; } @Override public boolean onSingleTapUp(MotionEvent e) { return true; } @Override public void onLongPress(MotionEvent e) { // 长按事件处理 } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // 滑动事件处理 return true; } }); mScaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureDetector.SimpleOnScaleGestureListener() { @Override public boolean onScale(ScaleGestureDetector detector) { mScaleFactor *= detector.getScaleFactor(); mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f)); // 设置缩放比例的上限和下限 invalidate(); // 重绘View return true; } }); } @Override public boolean onTouchEvent(MotionEvent event) { mGestureDetector.onTouchEvent(event); mScaleGestureDetector.onTouchEvent(event); return true; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.save(); canvas.scale(mScaleFactor, mScaleFactor); // 绘制View的内容 canvas.restore(); } } ``` 2. 所有子控件也随着缩放的layout 如果要实现所有子控件随着缩放比例进行缩放,可以在ViewGroup的onLayout方法中遍历所有子控件,根据缩放比例重新计算子控件的位置和大小。示例代码如下: ``` public class MyViewGroup extends ViewGroup { private float mScaleFactor = 1.0f; public MyViewGroup(Context context) { super(context); } public MyViewGroup(Context context, AttributeSet attrs) { super(context, attrs); } public MyViewGroup(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); int left = (int) (child.getLeft() * mScaleFactor); int top = (int) (child.getTop() * mScaleFactor); int right = (int) (child.getRight() * mScaleFactor); int bottom = (int) (child.getBottom() * mScaleFactor); child.layout(left, top, right, bottom); } } @Override protected void dispatchDraw(Canvas canvas) { canvas.save(); canvas.scale(mScaleFactor, mScaleFactor); super.dispatchDraw(canvas); canvas.restore(); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { super.dispatchTouchEvent(ev); return true; } @Override public boolean onTouchEvent(MotionEvent event) { mGestureDetector.onTouchEvent(event); mScaleGestureDetector.onTouchEvent(event); return true; } private GestureDetector mGestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() { @Override public boolean onDown(MotionEvent e) { return true; } @Override public boolean onSingleTapUp(MotionEvent e) { return true; } @Override public void onLongPress(MotionEvent e) { // 长按事件处理 } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // 滑动事件处理 return true; } }); private ScaleGestureDetector mScaleGestureDetector = new ScaleGestureDetector(getContext(), new ScaleGestureDetector.SimpleOnScaleGestureListener() { @Override public boolean onScale(ScaleGestureDetector detector) { mScaleFactor *= detector.getScaleFactor(); mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f)); // 设置缩放比例的上限和下限 requestLayout(); // 重新布局View return true; } }); } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值