android - Gone'd view draws on top during LayoutTransition.DISAPPEARING animator -


i'm using layouttransition fade view translucent background in , out when set visibility visible , gone respectively. standard stuff. have view solid background on top of (after, in xml) transitioning view. expect user see top view solid background unchanged throughout transition, opposite of animation runs when overlay view appears.

the appearing animator works expected: user can see top view throughout animation. disappearing animator not work expected: overlay view ends drawing on top of other views.

it's may worth noting happens if don't set own layouttransition , instead rely on android:animatelayoutchanges="true" in xml; added own increase duration, making easier see transition.

any thoughts on how workaround issue? i'm guessing pretty common , must missing obvious default behavior. i've tried few things attaching animatorupdatelistener invalidate top view every frame, setting own disappearing objectanimator update listener invalidates top view every frame, , replacing overlay view textview , other view types in case framelayout behaves in special way.

if replace transition animators regular objectanimator expected behavior, except view not gone , accepts touch events , junk (which makes "solution" untenable). don't think issue merely transitioning view has associated animator. seems issue layouttransition code or calls said.

mainactivity:

public class mainactivity extends appcompatactivity {     @override     protected void oncreate(bundle savedinstancestate) {         super.oncreate(savedinstancestate);         setcontentview(r.layout.activity_main);          final view overlay = findviewbyid(r.id.overlay);          final layouttransition lt = new layouttransition();          lt.setduration(layouttransition.appearing, 300);         lt.setstartdelay(layouttransition.appearing, 0);         lt.setduration(layouttransition.disappearing, 1000);         lt.setstartdelay(layouttransition.disappearing, 0);         ((viewgroup) overlay.getparent()).setlayouttransition(lt);          final runnable runnable = new runnable() {             @override             public void run() {                 if (overlay.getvisibility() == view.visible) {                     overlay.setvisibility(view.gone);                 } else {                     overlay.setvisibility(view.visible);                 }                  overlay.postdelayed(this, 1500);             }         };          overlay.post(runnable);     } } 

activity_main.xml:

<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"                 xmlns:tools="http://schemas.android.com/tools"                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:background="#ffffff"                 android:paddingbottom="@dimen/activity_vertical_margin"                 android:paddingleft="@dimen/activity_horizontal_margin"                 android:paddingright="@dimen/activity_horizontal_margin"                 android:paddingtop="@dimen/activity_vertical_margin"                 tools:context=".mainactivity"     >      <textview         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:background="#ff0000"         android:text="this behind overlay , should tint"         android:textcolor="#ffffff"         />      <framelayout         android:id="@+id/overlay"         android:layout_width="match_parent"         android:layout_height="match_parent"         android:background="#7f00ff00"         />      <textview         android:layout_width="match_parent"         android:layout_height="match_parent"         android:layout_centerinparent="true"         android:layout_margin="64dp"         android:background="#ffffff"         android:gravity="center"         android:text="this view in front of overlay , should not suffer tinting"         android:textcolor="#000000"         android:textsize="32sp"         />  </relativelayout> 

my device runs api 22 , i've set targetsdkversion 22 well. created whole new project , modified generated mainactivity , activity_main.xml match these pasted files (i've excluded import , package lines brevity).

i came cross same problem today, checked out viewgroup.java source code. result disappearing children draw on others.

this snippet of viewgroup.dispatchdraw(canvas) in api 23 , pretty sure same in api 22.

for (int = 0; < childrencount; i++) {     while (transientindex >= 0 && mtransientindices.get(transientindex) == i) {         final view transientchild = mtransientviews.get(transientindex);         if ((transientchild.mviewflags & visibility_mask) == visible ||                 transientchild.getanimation() != null) {             more |= drawchild(canvas, transientchild, drawingtime);         }         transientindex++;         if (transientindex >= transientcount) {             transientindex = -1;         }     }     int childindex = customorder ? getchilddrawingorder(childrencount, i) : i;     final view child = (preorderedlist == null)             ? children[childindex] : preorderedlist.get(childindex);     if ((child.mviewflags & visibility_mask) == visible || child.getanimation() != null) {         more |= drawchild(canvas, child, drawingtime);     } } while (transientindex >= 0) {     // there may additional transient views after normal views     final view transientchild = mtransientviews.get(transientindex);     if ((transientchild.mviewflags & visibility_mask) == visible ||             transientchild.getanimation() != null) {         more |= drawchild(canvas, transientchild, drawingtime);     }     transientindex++;     if (transientindex >= transientcount) {         break;     } } if (preorderedlist != null) preorderedlist.clear();  // draw disappearing views have animations if (mdisappearingchildren != null) {     final arraylist<view> disappearingchildren = mdisappearingchildren;     final int disappearingcount = disappearingchildren.size() - 1;     // go backwards -- may delete animations finish     (int = disappearingcount; >= 0; i--) {         final view child = disappearingchildren.get(i);         more |= drawchild(canvas, child, drawingtime);     } } 

gone'd views in mdisappearingchildren.

as source code said, normal views , transient views draw first, disappearing views draw. disappearing children draw on others. app developers can not change order.

my suggestion don't use layouttransition, write animation yourself.

edit:

i found trick draw disappearing children before other views, reflect required.

you need dump view make disappearing children replace in viewgroup.drawchild(canvas, view, long).

an example here.

public class tricklayout extends framelayout {      private field mdisappearingchildrenfield;     private arraylist<view> msuperdisappearingchildren;     // dump view draw disappearing children     // maybe need more 1 dump view     private view mdumpview;     private boolean mdotrick;      public tricklayout(context context) {         super(context);         init(context);     }      public tricklayout(context context, attributeset attrs) {         super(context, attrs);         init(context);     }      public tricklayout(context context, attributeset attrs, int defstyleattr) {         super(context, attrs, defstyleattr);         init(context);     }      private void init(context context) {         try {             mdisappearingchildrenfield = viewgroup.class.getdeclaredfield("mdisappearingchildren");             mdisappearingchildrenfield.setaccessible(true);         } catch (nosuchfieldexception e) {             // ignore         }          if (mdisappearingchildrenfield != null) {             // can add dump view in xml or somewhere else in code             mdumpview = new view(context);             addview(mdumpview, layoutparams.match_parent, layoutparams.match_parent);         }     }       @suppresswarnings("unchecked")     private void getsuperdisappearingchildren() {         if (mdisappearingchildrenfield == null || msuperdisappearingchildren != null) {             return;         }          try {             msuperdisappearingchildren = (arraylist<view>) mdisappearingchildrenfield.get(this);         } catch (illegalaccessexception e) {             // ignore         }     }      private boolean iwanttodothetrick() {         // need trick?         return true;     }      private boolean beforedispatchdraw() {         getsuperdisappearingchildren();          if (msuperdisappearingchildren == null ||                 msuperdisappearingchildren.size() <= 0 || getchildcount() <= 1) { // dump view included             return false;         }          return iwanttodothetrick();     }      private void afterdispatchdraw() {         // clean here     }      @override     protected void dispatchdraw(canvas canvas) {         mdotrick = beforedispatchdraw();         super.dispatchdraw(canvas);         if (mdotrick) {             afterdispatchdraw();             mdotrick = false;         }     }      @override     protected boolean drawchild(canvas canvas, view child, long drawingtime) {         arraylist<view> disappearingchildren = msuperdisappearingchildren;          if (mdotrick) {             if (child == mdumpview) {                 boolean more = false;                 (int = disappearingchildren.size() - 1; >= 0; i--) {                     more |= super.drawchild(canvas, disappearingchildren.get(i), drawingtime);                 }                 return more;             } else if (disappearingchildren.contains(child)) {                 // skip                 return false;             }         }          return super.drawchild(canvas, child, drawingtime);     } } 

Comments

Popular posts from this blog

1111. appearing after print sequence - php -

java - WARN : org.springframework.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/board/] in DispatcherServlet with name 'appServlet' -

Ruby on Rails, ActiveRecord, Postgres, UTF-8 and ASCII-8BIT encodings -