smoke and mirrors
play

Smoke and Mirrors the Magic behind wonderful UI in Android Israel - PowerPoint PPT Presentation

Smoke and Mirrors the Magic behind wonderful UI in Android Israel Ferrer Camacho @rallat Smoke and mirrors N. Amer. the obscuring or embellishing of the truth. Android Framework RecyclerView LayoutManager getViewForPosition RecyclerView


  1. Smoke and Mirrors the Magic behind wonderful UI in Android

  2. Israel Ferrer Camacho @rallat

  3. Smoke and mirrors N. Amer. the obscuring or embellishing of the truth.

  4. Android Framework

  5. RecyclerView LayoutManager getViewForPosition RecyclerView bindViewHolder getViewType getViewHolderByType Adapter RecyclePool

  6. Shared Element Transitions ActivityTransitionState startExit/startEnter ActivityTransitionCoordinator beginDelayedTransition TransitionManager

  7. ViewOverlay LinearLayout ViewOverlay of the LinearLayout ViewOverlay.add( );

  8. ViewOverlay LinearLayout re-layout ViewOverlay of the LinearLayout

  9. 
 
 
 
 /** 
 * A transition listener receives notifications from a transition. 
 * Notifications indicate transition lifecycle events. 
 */ 
 public static interface TransitionListener { 
 
 void onTransitionStart(Transition transition); 
 void onTransitionEnd(Transition transition); 
 void onTransitionCancel(Transition transition); 
 void onTransitionPause(Transition transition); 
 void onTransitionResume(Transition transition); 
 } 


  10. private View.OnTouchListener touchEater = new View.OnTouchListener() { 
 @Override 
 public boolean onTouch(View view, MotionEvent motionEvent) { 
 return true; 
 } 
 };

  11. Important attributes

  12. ClipChildren

  13. <?xml version="1.0" encoding="utf-8"?> 
 <FrameLayout 
 android:id="@+id/parent" 
 xmlns:android="http://schemas.android.com/apk/res/android" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 android:padding="@dimen/activity_vertical_margin"> 
 <FrameLayout 
 android:layout_width="300dp" 
 android:layout_height="300dp" 
 android:background="@color/colorAccent" 
 android:clipChildren="false" > 
 <FrameLayout 
 android:layout_width="200dp" 
 android:layout_height="200dp" 
 android:background="@color/colorPrimary"> 
 <ImageView 
 android:id="@+id/imageview" 
 android:layout_width="100dp" 
 android:layout_height="100dp" 
 android:src="@drawable/profile"/> 
 </FrameLayout> 
 </FrameLayout> 
 </FrameLayout> 


  14. <?xml version="1.0" encoding="utf-8"?> 
 <FrameLayout 
 android:id="@+id/parent" 
 xmlns:android="http://schemas.android.com/apk/res/android" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 android:clipChildren=“false" 
 android:padding="@dimen/activity_vertical_margin"> 
 <FrameLayout 
 android:layout_width="300dp" 
 android:layout_height="300dp" 
 android:background="@color/colorAccent" 
 android:clipChildren="false" > 
 <FrameLayout 
 android:layout_width="200dp" 
 android:layout_height="200dp" 
 android:background="@color/colorPrimary"> 
 <ImageView 
 android:id="@+id/imageview" 
 android:layout_width="100dp" 
 android:layout_height="100dp" 
 android:src="@drawable/profile"/> 
 </FrameLayout> 
 </FrameLayout> 
 </FrameLayout>

  15. ClipPadding

  16. 
 Utils public static void disableParentsClip(@NonNull View view) { 
 while (view.getParent() != null && view.getParent() instanceof ViewGroup) { 
 ViewGroup viewGroup = (ViewGroup) view.getParent(); 
 viewGroup.setClipChildren(false); 
 viewGroup.setClipToPadding(false); 
 view = viewGroup; 
 } 
 } 
 public static void enableParentsClip(@NonNull View view) { 
 while (view.getParent() != null && view.getParent() instanceof ViewGroup) { 
 ViewGroup viewGroup = (ViewGroup) view.getParent(); 
 viewGroup.setClipChildren(true); 
 viewGroup.setClipToPadding(true); 
 view = viewGroup; 
 } 


  17. Smoke and mirrors Lesson: Almost anything fast enough will look good

  18. Smoke and mirrors Lesson: Fake it until you make it.

  19. Demo

  20. Pivot

  21. /** 
 * Sets the x location of the point around which the view * is { @link #setRotation(float) rotated} and * { @link #setScaleX(float) scaled}. 
 * By default, the pivot point is centered on the object. * / smallRecyclerView.setPivotX(0); smallRecyclerView.setPivotY(0); mediumRecyclerView.setPivotX(0); 
 mediumRecyclerView.setPivotY(0);

  22. 
 smallRecyclerView.setAdapter(smallAdapter); mediumRecyclerView.setAdapter(mediumAdapter); 
 mediumRecyclerView.setVisibility( INVISIBLE ); 


  23. 
 ItemTouchListenerDispatcher dispatcher = new ItemTouchListenerDispatcher(this, galleryGestureDetector, fullScreenGestureDetector); smallRecyclerView.addOnItemTouchListener(onItemTouchListener); 
 mediumRecyclerView.addOnItemTouchListener(onItemTouchListener);

  24. 
 public class ItemTouchListenerDispatcher implements RecyclerView.OnItemTouchListener { 
 … 
 @Override 
 public void onTouchEvent(RecyclerView rv, MotionEvent e) { 
 currentSpan = getSpan(e); 
 switch (rv.getId()) { 
 case R.id. mediumRecyclerView : { 
 if (currentSpan < 0) { 
 galleryGestureDetector.onTouchEvent(e); 
 } else if (currentSpan == 0) { 
 final View childViewUnder = rv.findChildViewUnder(e.getX(), e.getY()); 
 if (childViewUnder != null) { 
 childViewUnder.performClick(); 
 } 
 } 
 break; 
 } 
 case R.id. smallRecyclerView : { 
 galleryGestureDetector.onTouchEvent(e); 
 break; 
 } 
 default: { 
 break; 
 } 
 } 
 } 
 …

  25. 
 public class ItemTouchListenerDispatcher implements RecyclerView.OnItemTouchListener { 
 … 
 @Override 
 public void onTouchEvent(RecyclerView rv, MotionEvent e) { 
 currentSpan = getSpan(e); 
 switch (rv.getId()) { 
 case R.id. mediumRecyclerView : { 
 if (currentSpan < 0) { 
 galleryGestureDetector.onTouchEvent(e); 
 } else if (currentSpan == 0) { 
 final View childViewUnder = rv.findChildViewUnder(e.getX(), e.getY()); 
 if (childViewUnder != null) { 
 childViewUnder.performClick(); 
 } 
 } 
 break; 
 } 
 case R.id. smallRecyclerView : { 
 galleryGestureDetector.onTouchEvent(e); 
 break; 
 } 
 default: { 
 break; 
 } 
 } 
 } 
 …

  26. 
 public class ItemTouchListenerDispatcher implements RecyclerView.OnItemTouchListener { 
 … 
 @Override 
 public void onTouchEvent(RecyclerView rv, MotionEvent e) { 
 currentSpan = getSpan(e); 
 switch (rv.getId()) { 
 case R.id. mediumRecyclerView : { 
 if (currentSpan < 0) { 
 galleryGestureDetector.onTouchEvent(e); 
 } else if (currentSpan == 0) { 
 final View childViewUnder = rv.findChildViewUnder(e.getX(), e.getY()); 
 if (childViewUnder != null) { 
 childViewUnder.performClick(); 
 } 
 } 
 break; 
 } 
 case R.id. smallRecyclerView : { 
 galleryGestureDetector.onTouchEvent(e); 
 break; 
 } 
 default: { 
 break; 
 } 
 } 
 } 
 …

  27. 
 public class ItemTouchListenerDispatcher implements RecyclerView.OnItemTouchListener { 
 … 
 @Override 
 public void onTouchEvent(RecyclerView rv, MotionEvent e) { 
 currentSpan = getSpan(e); 
 switch (rv.getId()) { 
 case R.id. mediumRecyclerView : { 
 if (currentSpan < 0) { 
 galleryGestureDetector.onTouchEvent(e); 
 } else if (currentSpan == 0) { 
 final View childViewUnder = rv.findChildViewUnder(e.getX(), e.getY()); 
 if (childViewUnder != null) { 
 childViewUnder.performClick(); 
 } 
 } 
 break; 
 } 
 case R.id. smallRecyclerView : { 
 galleryGestureDetector.onTouchEvent(e); 
 break; 
 } 
 default: { 
 break; 
 } 
 } 
 } 
 …

  28. Scaling with gesture

  29. 
 
 public interface OnScaleGestureListener { 
 /** 
 * Responds to scaling events for a gesture in progress. 
 * Reported by pointer motion. 
 */ 
 public boolean onScale(ScaleGestureDetector detector); 
 /** 
 * Responds to the beginning of a scaling gesture. Reported by 
 * new pointers going down. 
 */ 
 public boolean onScaleBegin(ScaleGestureDetector detector); 
 /** 
 * Responds to the end of a scale gesture. Reported by existing 
 * pointers going up. 
 
 * @param detector The detector reporting the event - use this to 
 * retrieve extended info about event state. 
 */ 
 public void onScaleEnd(ScaleGestureDetector detector); 
 }

  30. Scale begin @Override 
 public boolean onScaleBegin(@NonNull ScaleGestureDetector detector) { 
 mediumRecyclerView.setVisibility(View. VISIBLE ); 
 smallRecyclerView.setVisibility(View. VISIBLE ); 
 return true; 
 }

Recommend


More recommend