简体   繁体   English

刷新时,Android自定义视图会移回原始位置

[英]Android Custom View move back to original position when refreshing

I'm implementing a time picker which looks like this: 我正在实现一个时间选择器,如下所示:

未完成的时间选择器

That yellow block is MyCustomView . 黄色块是MyCustomView When moving MyCustomView , I should calculate new date and set tvDate . 移动MyCustomView ,我应该计算新日期并设置tvDate

partial layout file: 部分布局文件:

<LinearLayout 
    android:orientation="vertical">

    <TextView android:id="@+id/tv_date">

    <RelativeLayout 
        android:id="@+id/rl">

        <MyCustomView
         android:layout_centerInParent="true"/>

        <OtherViews/>
    </RelativeLayout>
</LinearLayout>

code: 码:

class MyCustomView extends View{

    // move listener
    public interface IMoveCallback{
        void update(int index);
    }

    private IMoveCallback listener = null; 

    // set listener
    public void setMoveCallback(IMoveCallback callback){
        this.listener = callback;
    }

    @Override
    protected void onDraw(Canvas c){
        super.onDraw(c);
        // draw yellow block and four arrows here.
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        processDrag(v, event);
        invalidate();
        return false;
    }

    private void processDrag(View v, MotionEvent event){
        // calculate new position(left, top, right, bottom)
        v.layout(newLeft, newTop, newRight, newBottom); 
        if(listener != null){
            // calculate index by new position
            listener.update(index);
        }
    }
}

class MainActivity extends Activity implements MyCustomView.IMoveCallback{

    MyCustomView view; // view.setMoveCallback(MainActivity.this)

    @Override
    public void update(int index){
        tvDate.setText(String.valueOf(System.currentTimeMillis()))//update tvDate
    }
}

If tvDate.setText() is removed, MyCustomView follows the finger, like this: 如果删除了tvDate.setText()MyCustomView跟随手指,如下所示:

在此输入图像描述

If I update tvDate , MyCustomView moves back to the center of rl : 如果我更新tvDateMyCustomView会移回到rl的中心:

在此输入图像描述

I don't think it an activity-lifecycle issue. 我不认为这是一个活动 - 生命周期问题。 Someone mentioned ((MarginLayoutParams)rl.getLayoutParams()).topMargin but did not explain why. 有人提到过((MarginLayoutParams)rl.getLayoutParams()).topMargin但没有解释原因。
Anybody can help me? 有人可以帮帮我吗?

Your solution is to invalidate your CustomView after you TextView.setText() setText() before you layout or pass in values for your left, rigth, ... 你的解决方案是在布局之前 TextView.setText() setText() 之后 invalidate你的 CustomView invalidate 或者为你的左边,rigth传递值...

private void processDrag(View v, MotionEvent event){       
    if(listener != null){
        // calculate index by new position
        listener.update(index);
    }        
    // calculate new position(left, top, right, bottom)
    v.layout(newLeft, newTop, newRight, newBottom); 
}
//i think you should take out invalidate() in your onTouch()

Why? 为什么? TextView.setText() triggers invalidate & requestLayout() at them same time to force a quick layout, but Invalidate() just tells its parent that it is dirty, so it needs to do a top down layout pass. TextView.setText()触发invalidaterequestLayout()以强制快速布局,但Invalidate()只是告诉其父级它是脏的,所以它需要做一个自上而下的布局传递。

( im confused so i won't continue to back this up, hence i jump ). 我很困惑,所以我不会继续支持这个,因此我跳了 )。 Your TextView is inside a parent layout who's grand child is your custom view, and invalidate() , re-lays all of them hence sends your custom view back to its position, however if you exclude that, and call an explicit invalidate() in your Custom view it tells it parent that its dirty and the same process happens, but this time only with the RelativeLayout 您的TextView位于父级布局中,其子孙是您的自定义视图,而invalidate() ,重新放置所有这些,因此将您的自定义视图发送回其位置,但是如果您排除它,并调用显式的invalidate() in它的自定义视图告诉它父进程它的脏和相同的进程发生,但这次只有RelativeLayout

user: Zaid Qureshi has already made this points known to you. 用户:Zaid Qureshi已经知道了这一点。

Also i do not know if you know that the layoutParams being given to your customView is from the parent who you do not control much but the os, and the injected Params are what is uses to layout and give padding etc etc to your View, and since you do not lay them out but just passes positions. 另外我不知道你是否知道给你的customView提供的layoutParams来自你不能控制很多但是操作系统的父系,并且注入的Params用于布局和给你的视图等填充等等,以及因为你没有把它们排好,而只是通过位置。

Hope i make sense to you & it helps 希望我对你有意义并且有所帮助

You need to save the location of your view and render it at the same spot when the activity resumes(coming back from home) or starts(coming back after pressing back). 您需要保存视图的位置,并在活动恢复(从家中回来)或开始(在按下后返回)时将其呈现在同一位置。 This Picture shows methods you can override to achieve that such as onPause when losing focus etc. 此图片显示了您可以覆盖以实现该方法的方法,例如失去焦点时的onPause等。

EDIT 编辑

From the looks of it, it is resetting back to its original state. 从它的外观来看,它正在重置回原始状态。 Post more about how you are setting the location etc. If that is a view you are moving. 发布更多关于如何设置位置的信息等。如果这是一个你正在移动的视图。 Then implement a on drag listener instead of that update. 然后实现一个on drag listener而不是该更新。 And let me know how that works out. 让我知道这是如何工作的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM