【问题标题】:Android Custom View move back to original position when refreshing刷新时Android自定义视图移回原始位置
【发布时间】:2016-06-23 07:20:58
【问题描述】:

我正在实现一个时间选择器,如下所示:

那个黄色方块是MyCustomView。移动MyCustomView 时,我应该计算新日期并设置tvDate

部分布局文件:

<LinearLayout 
    android:orientation="vertical">

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

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

        <MyCustomView
         android:layout_centerInParent="true"/>

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

代码:

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
    }
}

如果tvDate.setText() 被移除,MyCustomView 会跟随手指,如下所示:

如果我更新tvDateMyCustomView 会移回rl 的中心:

我认为这不是活动生命周期问题。有人提到((MarginLayoutParams)rl.getLayoutParams()).topMargin,但没有解释原因。
有人可以帮帮我吗?

【问题讨论】:

  • 你应该更具体。 “原来的位置”是什么意思?
  • 还显示活动的完整代码。这可能是一个活动生命周期问题
  • @FarhadFaghihi 我已经编辑了我的问题。 MainActivity 包含 onCreate 和回调。我不认为这是一个活动生命周期问题。

标签: java android android-layout android-studio android-custom-view


【解决方案1】:

您的解决方案是 invalidate 您的 CustomView 在您 TextView.setText() setText() 在您布局或传递左、右、...的值之前

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()

为什么? TextView.setText() 同时触发 invalidaterequestLayout() 以强制进行快速布局,但 Invalidate() 只是告诉其父级它是脏的,因此它需要进行自上而下的布局传递。

我很困惑,所以我不会继续支持这一点,因此我跳了)。您的 TextView 位于父布局内,其孙子是您的自定义视图,invalidate() 重新放置所有这些视图,因此将您的自定义视图发送回其位置,但是如果您排除它,并调用显式 @987654332 @ 在您的自定义视图中,它告诉它的父级它的脏和相同的过程发生了,但这次只有RelativeLayout

用户:Zaid Qureshi 已经向您说明了这一点。

另外我不知道你是否知道你的 customView 的 layoutParams 来自你控制不多但操作系统的父级,注入的 Params 用于布局和填充等查看,因为您不布置它们而只是传递位置。

希望我对你有意义并且对你有帮助

【讨论】:

    【解决方案2】:

    您需要保存视图的位置,并在活动恢复(从家回来)或开始(按返回后返回)时将其呈现在同一位置。 This Picture 显示了您可以覆盖的方法,例如失去焦点时的 onPause 等。

    编辑

    从外观上看,它正在恢复到原来的状态。发布更多关于您如何设置位置等的信息。如果这是您正在移动的视图。然后实现 on drag listener 而不是该更新。让我知道结果如何。

    【讨论】:

    • 我在MyCustomView.onTouch(View v, MotionEvent motionEvent)中通过v.layout(left, top, right, bottom)设置位置
    • 只有当你调用更新方法时才会发生?尝试过做 v.layout,做 this.layout.. 也可以在更新文本后尝试更新布局。
    • 是的,只有在tvDate.setText()时才会发生。
    • 尝试摆脱你的无效。因为 TextView 可能已经在调用它来刷新视图。还存储新的左右位置,并在绘图之前再次将其分配给布局,也许这会有所帮助。所以代替 v.layout 做这个布局,并在绘制之前再试一次
    • 在您的 onTouch 中也返回 true,因为您对此视图中的其他事件感兴趣
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-08
    • 1970-01-01
    • 1970-01-01
    • 2017-06-15
    • 1970-01-01
    • 1970-01-01
    • 2018-10-25
    相关资源
    最近更新 更多