Anthony Cooper
Anthony Cooper

Reputation: 465

Android Custom View move back to original position when refreshing

I'm implementing a time picker which looks like this:

unfinished time picker

That yellow block is MyCustomView. When moving MyCustomView, I should calculate new date and set 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:

enter image description here

If I update tvDate, MyCustomView moves back to the center of rl:

enter image description here

I don't think it an activity-lifecycle issue. Someone mentioned ((MarginLayoutParams)rl.getLayoutParams()).topMargin but did not explain why.
Anybody can help me?

Upvotes: 5

Views: 1887

Answers (2)

Elltz
Elltz

Reputation: 10859

Your solution is to invalidate your CustomView after you TextView.setText() setText() before you layout or pass in values for your left, 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.

(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

user: Zaid Qureshi has already made this points known to you.

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.

Hope i make sense to you & it helps

Upvotes: 1

Zaid Qureshi
Zaid Qureshi

Reputation: 1213

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.

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. And let me know how that works out.

Upvotes: 0

Related Questions