rotary_selector: add more animation for page transition (text, page arrow) 70/164870/1
authorThiep Ha <thiep.ha@samsung.com>
Wed, 20 Dec 2017 05:13:40 +0000 (14:13 +0900)
committerThiep Ha <thiep.ha@samsung.com>
Wed, 20 Dec 2017 08:20:43 +0000 (17:20 +0900)
Change-Id: I85d641880726cef81e958caf358266be72d58752

inc/wearable/efl_extension_common_private.h
src/wearable/efl_extension_rotary_selector.c

index ae2f395f79a205bc8e2cb93cf863c66b55d72684..048d2d64e855deb3af23149cc01ca17ebf762d34 100644 (file)
@@ -114,6 +114,10 @@ struct _Eext_Rotary_Selector_Data {
    Eina_Bool next_page_animation_started;
    Eina_Bool previous_page_animation_started;
    Ecore_Timer *next_page_timer;
+   Ecore_Timer *content_update_timer;
+   Ecore_Animator *content_animator;
+   double content_animator_start_time;
+   Eina_Bool content_animator_started;
    Eina_Bool end_effect_animation_started;
    double end_effect_animator_start_time;
    Ecore_Animator *end_effect_animator;
index 5fae35ad00f931e49e8525c0f3ffbf3c161f2fb5..28a56aa2018a7a795a615b7bd4826c9485e5d954 100644 (file)
 #define _ROTARY_SELECTOR_ITEM_DIVISION_ANGLE 30
 #define _ROTARY_SELECTOR_PAGE_ITEM_MAX 11
 #define _ROTARY_SELECTOR_PAGE_ANIMATION_DURATION 0.3
+#define _ROTARY_SELECTOR_PAGE_TEXT_ANIMATION_DURATION 0.2
 #define _ROTARY_SELECTOR_DRAG_ANIMATION_DURATION 0.2
 #define _ROTARY_SELECTOR_DEL_ANIMATION_DURATION 0.2
-#define _ROTARY_SELECTOR_NEXT_PAGE_ANIMATION_DELAY_TIME 0.1
+#define _ROTARY_SELECTOR_NEXT_PAGE_ANIMATION_DELAY_TIME 0.15
 #define _ROTARY_SELECTOR_END_EFFECT_ANIMATION_DURATION 0.6
 #define _ROTARY_SELECTOR_CUBIC_BEZIER_P1_X 0.25
 #define _ROTARY_SELECTOR_CUBIC_BEZIER_P1_Y 0.46
@@ -222,13 +223,16 @@ static void _item_update_animation_run(Eext_Rotary_Selector_Data *rsd);
 static Eina_Bool _next_page_animator_cb(void *data);
 static Eina_Bool _next_page_timer_cb(void *data);
 static Eina_Bool _end_effect_animator_cb(void *data);
+static Eina_Bool _content_show_cb(void *data);
+static Eina_Bool _content_hide_cb(void *data);
 
 // ----------------------------------------- selector API --------------------------------------//
-static void _selector_update(Eext_Rotary_Selector_Data *rsd, Eina_Bool page_changed, Eina_Bool is_animation);
+static void _selector_update(Eext_Rotary_Selector_Data *rsd, Eina_Bool page_changed, Eina_Bool is_anim, Eina_Bool text_anim);
 static void _selector_content_update(Eext_Rotary_Selector_Data *rsd);
 static void _selector_clicked_signal(void *data, Evas_Object *obj, const char *emission, const char *source);
 static void _selector_animation_finished_cb(void *data, Evas_Object *obj, const char *emission, const char *source);
 static void _editing_mode_turnoff(Eext_Rotary_Selector_Data *rsd);
+static Eina_Bool _content_update_timer_cb(void *data);
 
 // ----------------------------------------- Accessibility API --------------------------------------//
 static void _accessibility_item_btn_highlighted_cb(void *data, Evas_Object *obj, void *event_info);
@@ -430,12 +434,12 @@ _page_move(void *data)
    if (rsd->stand_dir == EEXT_ROTARY_SELECTOR_DIRECTION_CW)
      {
         _page_animation_run(rsd, EINA_FALSE);
-        _selector_update(rsd, EINA_TRUE, EINA_TRUE);
+        _selector_update(rsd, EINA_TRUE, EINA_TRUE, EINA_TRUE);
      }
    else
      {
         _page_animation_run(rsd, EINA_TRUE);
-        _selector_update(rsd, EINA_TRUE, EINA_TRUE);
+        _selector_update(rsd, EINA_TRUE, EINA_TRUE, EINA_TRUE);
      }
    rsd->stand_timer = NULL;
 
@@ -1081,7 +1085,7 @@ _event_area_mouse_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
                   rsd->selected_index = first_index - 1;
                   _item_selected_signal_send(rsd, previous_item_index, rsd->selected_index);
                   _page_animation_run(rsd, EINA_FALSE);
-                  _selector_update(rsd, EINA_TRUE, EINA_TRUE);
+                  _selector_update(rsd, EINA_TRUE, EINA_TRUE, EINA_TRUE);
                   evas_object_smart_callback_call(rsd->rotary_selector, "item,selected", (void*)_item_get(rsd, rsd->selected_index));
                }
           }
@@ -1092,7 +1096,7 @@ _event_area_mouse_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
                   rsd->selected_index = last_index + 1;
                   _item_selected_signal_send(rsd, previous_item_index, rsd->selected_index);
                   _page_animation_run(rsd, EINA_TRUE);
-                  _selector_update(rsd, EINA_TRUE, EINA_TRUE);
+                  _selector_update(rsd, EINA_TRUE, EINA_TRUE, EINA_TRUE);
                   evas_object_smart_callback_call(rsd->rotary_selector, "item,selected", (void*)_item_get(rsd, rsd->selected_index));
                }
           }
@@ -1141,7 +1145,7 @@ _event_area_mouse_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
                        _item_touched_signal_send(rsd, rsd->pressed_item_index, EINA_FALSE, EINA_TRUE);
                        rsd->selected_index = new_index;
                        _item_selected_signal_send(rsd, previous_item_index, rsd->selected_index);
-                       _selector_update(rsd, EINA_FALSE, EINA_FALSE);
+                       _selector_update(rsd, EINA_FALSE, EINA_FALSE, EINA_FALSE);
                        evas_object_smart_callback_call(rsd->rotary_selector, "item,clicked", (void*)_item_get(rsd, rsd->selected_index));
                     }
                }
@@ -1421,7 +1425,7 @@ _rotary_selector_rotary_cb(void *data, Evas_Object *obj, Eext_Rotary_Event_Info
              if (last_index < rsd->selected_index)
                {
                   _page_animation_run(rsd, EINA_TRUE);
-                  _selector_update(rsd, EINA_TRUE, EINA_TRUE);
+                  _selector_update(rsd, EINA_TRUE, EINA_TRUE, EINA_TRUE);
                   //for accessibility
                   if (elm_atspi_bridge_utils_is_screen_reader_enabled())
                     {
@@ -1439,7 +1443,7 @@ _rotary_selector_rotary_cb(void *data, Evas_Object *obj, Eext_Rotary_Event_Info
                }
              else
                {
-                  _selector_update(rsd, EINA_FALSE, EINA_TRUE);
+                  _selector_update(rsd, EINA_FALSE, EINA_TRUE, EINA_FALSE);
 
                   //for accessibility
                   if (elm_atspi_bridge_utils_is_screen_reader_enabled())
@@ -1501,7 +1505,7 @@ _rotary_selector_rotary_cb(void *data, Evas_Object *obj, Eext_Rotary_Event_Info
              if (first_index > rsd->selected_index)
                {
                   _page_animation_run(rsd, EINA_FALSE);
-                  _selector_update(rsd, EINA_TRUE, EINA_TRUE);
+                  _selector_update(rsd, EINA_TRUE, EINA_TRUE, EINA_TRUE);
                   //for accessibility
                   if (elm_atspi_bridge_utils_is_screen_reader_enabled())
                     {
@@ -1519,7 +1523,7 @@ _rotary_selector_rotary_cb(void *data, Evas_Object *obj, Eext_Rotary_Event_Info
                }
              else
                {
-                  _selector_update(rsd, EINA_FALSE, EINA_TRUE);
+                  _selector_update(rsd, EINA_FALSE, EINA_TRUE, EINA_FALSE);
                   //for accessibility
                   if (elm_atspi_bridge_utils_is_screen_reader_enabled())
                     {
@@ -1666,6 +1670,16 @@ _rotary_selector_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
         ecore_animator_del(rsd->del_item_move_animator);
         rsd->del_item_move_animator = NULL;
      }
+   if (rsd->content_update_timer)
+     {
+        ecore_timer_del(rsd->content_update_timer);
+        rsd->content_update_timer = NULL;
+     }
+   if(rsd->content_animator)
+     {
+        ecore_animator_del(rsd->content_animator);
+        rsd->content_animator = NULL;
+     }
    if (rsd->prev_page)
      evas_object_del(rsd->prev_page);
    if (rsd->next_page)
@@ -1788,7 +1802,7 @@ _editing_mode_turnoff(Eext_Rotary_Selector_Data *rsd)
         _items_transformation_update(rsd);
         _items_invalidate(rsd);
      }
-   _selector_update(rsd, EINA_FALSE, EINA_FALSE);
+   _selector_update(rsd, EINA_FALSE, EINA_FALSE, EINA_FALSE);
    eext_object_event_callback_del(rsd->rotary_selector, EEXT_CALLBACK_BACK,
                                   _back_event_cb);
 }
@@ -1999,6 +2013,7 @@ _layer_items_invalidate(Eext_Rotary_Selector_Data *rsd)
              evas_object_stack_below(rsd->prev_page, btn);
           }
         elm_object_signal_emit(rsd->prev_page, "elm,selector,button,page,show", "elm");
+        evas_object_color_set(rsd->prev_page, 255, 255, 255, 255);
         evas_object_show(rsd->prev_page);
      }
    else
@@ -2027,6 +2042,7 @@ _layer_items_invalidate(Eext_Rotary_Selector_Data *rsd)
           }
 
         elm_object_signal_emit(rsd->next_page, "elm,selector,button,page,show", "elm");
+        evas_object_color_set(rsd->next_page, 255, 255, 255, 255);
         evas_object_show(rsd->next_page);
      }
    else
@@ -2064,7 +2080,7 @@ _item_select(Eext_Rotary_Selector_Data *rsd, int index)
    if (!rsd->editing)
      _item_selected_signal_send(rsd, rsd->selected_index, index);
    rsd->selected_index = index;
-   _selector_update(rsd, EINA_FALSE, EINA_FALSE);
+   _selector_update(rsd, EINA_FALSE, EINA_FALSE, EINA_FALSE);
    _items_transformation_update(rsd);
    _items_invalidate(rsd);
 }
@@ -2289,9 +2305,12 @@ _previous_page_animator_cb(void *data)
    int i = 0;
    int last_index = 0;
    double p = 0.0f;
-   double v[4] = {_ROTARY_SELECTOR_CUBIC_BEZIER_P1_X, _ROTARY_SELECTOR_CUBIC_BEZIER_P1_Y, _ROTARY_SELECTOR_CUBIC_BEZIER_P2_X, _ROTARY_SELECTOR_CUBIC_BEZIER_P2_Y};
+   double v[4] = {_ROTARY_SELECTOR_CUBIC_BEZIER_P1_X,
+                  _ROTARY_SELECTOR_CUBIC_BEZIER_P1_Y,
+                  _ROTARY_SELECTOR_CUBIC_BEZIER_P2_X,
+                  _ROTARY_SELECTOR_CUBIC_BEZIER_P2_Y};
 
-   int first_index = rsd->current_page*_ROTARY_SELECTOR_PAGE_ITEM_MAX;
+   int first_index = rsd->current_page * _ROTARY_SELECTOR_PAGE_ITEM_MAX;
 
    if (rsd->current_page == 0)
      {
@@ -2299,25 +2318,28 @@ _previous_page_animator_cb(void *data)
      }
    else
      {
-        last_index = (rsd->current_page + 1)*_ROTARY_SELECTOR_PAGE_ITEM_MAX - 1;
+        last_index = (rsd->current_page + 1) * _ROTARY_SELECTOR_PAGE_ITEM_MAX - 1;
      }
 
    if (rsd->previous_page_animation_started)
      {
         rsd->previous_page_animation_started = EINA_FALSE;
         rsd->previous_page_animator_start_time = ecore_time_unix_get();
+        rsd->next_page_timer = ecore_timer_add(_ROTARY_SELECTOR_NEXT_PAGE_ANIMATION_DELAY_TIME,
+                                               _next_page_timer_cb, rsd);
      }
 
    double dt = ecore_time_unix_get() - rsd->previous_page_animator_start_time;
-   p = ecore_animator_pos_map_n(dt /_ROTARY_SELECTOR_PAGE_ANIMATION_DURATION, ECORE_POS_MAP_CUBIC_BEZIER, 4, v);
+   p = ecore_animator_pos_map_n(dt / _ROTARY_SELECTOR_PAGE_ANIMATION_DURATION, ECORE_POS_MAP_CUBIC_BEZIER, 4, v);
 
    if (p <= 1.0f)
      {
-        const float startAngle[] = { 300.f, 330.f, 0.f, 30.f, 60.f, 90.f, 120.f, 150.f, 180.f, 210.f, 240.f };
+        const float startAngle[] = {-60.f, -30.f, 0.f, 30.f, 60.f, 90.f, 120.f, 150.f, 180.f, 210.f, 240.f};
+        Evas_Coord new_a;
 
+        new_a = 255 * (1 - p);
         EINA_LIST_FOREACH(rsd->item_list, l, item)
           {
-             Evas_Coord new_a;
              Evas_Object *button = item->base.obj;
              Eext_Rotary_Selector_Item_Coords *coords = &item->coords;
              evas_object_raise(button);
@@ -2329,29 +2351,73 @@ _previous_page_animator_cb(void *data)
                   if (rsd->animation_direction)
                     {
                        // page 0 --> 1 : 0page
-                       const float endAngle[] = { 660.f, 660.f, 300.f, 300.f, 300.f, 300.f, 300.f, 300.f, 300.f, 300.f, 300.f };
-                       _circle_path_interpolator(rsd, p, startAngle[item->index%_ROTARY_SELECTOR_PAGE_ITEM_MAX], endAngle[item->index%_ROTARY_SELECTOR_PAGE_ITEM_MAX], rsd->radius, rsd->radius, &coords->x, &coords->y, EINA_FALSE);
+                       const float endAngle[] = {105.f, 120.f, 135.f, 150.f, 165.f, 180.f, 195.f, 210.f, 225.f, 240.f, 255.f};
+                       _circle_path_interpolator(rsd, p, startAngle[item->index % _ROTARY_SELECTOR_PAGE_ITEM_MAX],
+                                                 endAngle[item->index % _ROTARY_SELECTOR_PAGE_ITEM_MAX],
+                                                 rsd->radius, rsd->radius, &coords->x, &coords->y, EINA_FALSE);
                     }
                   else
                     {
                        // page 1 --> 0 : 1page
-                       const float endAngle[] = { 240.f, 240.f, -120.f, -120.f, -120.f, -120.f, -120.f, -120.f, -120.f, -120.f, -120.f };
-                       _circle_path_interpolator(rsd, p, startAngle[item->index%_ROTARY_SELECTOR_PAGE_ITEM_MAX], endAngle[item->index%_ROTARY_SELECTOR_PAGE_ITEM_MAX], rsd->radius, rsd->radius, &coords->x, &coords->y, EINA_FALSE);
+                       const float endAngle[] = {-75.f, -60.f, -45.f, -30.f, -15.f, 0.f, 15.f, 30.f, 45.f, 60.f, 75.f};
+                       _circle_path_interpolator(rsd, p, startAngle[item->index % _ROTARY_SELECTOR_PAGE_ITEM_MAX],
+                                                 endAngle[item->index % _ROTARY_SELECTOR_PAGE_ITEM_MAX],
+                                                 rsd->radius, rsd->radius, &coords->x, &coords->y, EINA_FALSE);
                     }
-                  new_a = 255*(1-p);
                   evas_object_move(button, item->coords.x, item->coords.y);
-                  evas_object_color_set(button, new_a, new_a, new_a, new_a);
+                  evas_object_color_set(button, 255, 255, 255, new_a);
+
                }
-             if (rsd->animation_direction && rsd->current_page > 0 && (i == first_index-1 || i == first_index -2))
+             if (rsd->animation_direction && rsd->current_page > 0 &&
+                 (i == first_index - 1 || i == first_index - 2))
                {
                   evas_object_color_set(button, 0, 0, 0, 0);
                }
-             else if (last_index < (rsd->item_count - 1) && (i == last_index + 1 || i == last_index + 2))
+             else if (last_index < (rsd->item_count - 1) &&
+                      (i == last_index + 1 || i == last_index + 2))
                {
                   evas_object_color_set(button, 0, 0, 0, 0);
                }
              i++;
           }
+
+        Evas_Coord x, y;
+        double px, py;
+        double radius = _ROTARY_SELECTOR_SCREEN_WIDTH / 2.0f;
+        if (rsd->animation_direction)
+          {
+             //next page button
+             if (!rsd->next_page)
+               {
+                  rsd->next_page = elm_layout_add(rsd->rotary_selector);
+                  elm_layout_theme_set(rsd->next_page, "rotary_selector", "next_page", "default");
+                  evas_object_smart_member_add(rsd->next_page, rsd->rotary_selector);
+                  evas_object_show(rsd->next_page);
+               }
+             evas_object_geometry_get(rsd->rotary_selector, &x, &y, NULL, NULL);
+             _circle_path_interpolator(rsd, p, 255.f, 270.f, radius, radius,
+                                       &px, &py, EINA_TRUE);
+             evas_object_move(rsd->next_page, (Evas_Coord)(px + x + rsd->page_item_width * 0.5 - 6),
+                              (Evas_Coord)(py + y + rsd->page_item_height * 0.5 + 6));
+             evas_object_color_set(rsd->next_page, 255, 255, 255, new_a);
+          }
+        else
+          {
+             //previous page button
+             if (!rsd->prev_page)
+               {
+                  rsd->prev_page = elm_layout_add(rsd->rotary_selector);
+                  elm_layout_theme_set(rsd->prev_page, "rotary_selector", "previous_page", "default");
+                  evas_object_smart_member_add(rsd->prev_page, rsd->rotary_selector);
+                  evas_object_show(rsd->prev_page);
+               }
+             evas_object_geometry_get(rsd->rotary_selector, &x, &y, NULL, NULL);
+             _circle_path_interpolator(rsd, p, -90.f, -105.f, radius, radius,
+                                       &px, &py, EINA_TRUE);
+             evas_object_move(rsd->prev_page, (Evas_Coord)(px + x + rsd->page_item_width * 0.5 + 6 ),
+                              (Evas_Coord)(py + y + rsd->page_item_height * 0.5 + 12));
+             evas_object_color_set(rsd->prev_page, 255, 255, 255, new_a);
+          }
      }
    if (p >= 1.0f)
      {
@@ -2403,8 +2469,6 @@ _page_animation_run(Eext_Rotary_Selector_Data *rsd, Eina_Bool direction)
    rsd->previous_page_animator_start_time = ecore_loop_time_get();
    rsd->previous_page_animation_started = EINA_TRUE;
    rsd->previous_page_animator = ecore_animator_add(_previous_page_animator_cb, rsd);
-
-   rsd->next_page_timer = ecore_timer_add(_ROTARY_SELECTOR_NEXT_PAGE_ANIMATION_DELAY_TIME, _next_page_timer_cb, rsd);
 }
 
 static void
@@ -2474,6 +2538,7 @@ _next_page_animator_cb(void *data)
 
    if (p <= 1.0f)
      {
+        new_a = 255 * p;
         EINA_LIST_FOREACH(rsd->item_list, l, item)
           {
              button = item->base.obj;
@@ -2485,11 +2550,13 @@ _next_page_animator_cb(void *data)
                   if (first_index + _ROTARY_SELECTOR_PAGE_ITEM_MAX <= i && i<= last_index + _ROTARY_SELECTOR_PAGE_ITEM_MAX)    //current page+1
                     {
                        // page 0 --> 1 : 1page
-                       const float endAngle[] = { 300.f, 330.f, 360.f, 390.f, 420.f, 450.f, 480.f, 510.f, 540.f, 570.f, 600.f };
-                       _circle_path_interpolator(rsd, p, 300, endAngle[item->index%_ROTARY_SELECTOR_PAGE_ITEM_MAX], rsd->radius, rsd->radius, &coords->x, &coords->y, EINA_FALSE);
-                       new_a = 255*p;
+                       const float start_angle[] = {285.f, 300.f, 315.f, 330.f, 345.f, 360.f, 375.f, 390.f, 405.f, 420.f, 435.f};
+                       const float end_angle[] = {300.f, 330.f, 360.f, 390.f, 420.f, 450.f, 480.f, 510.f, 540.f, 570.f, 600.f};
+                       _circle_path_interpolator(rsd, p, start_angle[item->index % _ROTARY_SELECTOR_PAGE_ITEM_MAX],
+                                                 end_angle[item->index%_ROTARY_SELECTOR_PAGE_ITEM_MAX],
+                                                 rsd->radius, rsd->radius, &coords->x, &coords->y, EINA_FALSE);
                        evas_object_move(button, item->coords.x, item->coords.y);
-                       evas_object_color_set(button, new_a, new_a, new_a, new_a);
+                       evas_object_color_set(button, 255, 255, 255, new_a);
                        evas_object_show(button);
                     }
                }
@@ -2498,16 +2565,55 @@ _next_page_animator_cb(void *data)
                   if (first_index - _ROTARY_SELECTOR_PAGE_ITEM_MAX <= i && i<= last_index - _ROTARY_SELECTOR_PAGE_ITEM_MAX)    //current page-1
                     {
                        // page 1 --> 0 : 0page
-                       const float endAngle[] = { -60.f, -30.f, 0.f, 30.f, 60.f, 90.f, 120.f, 150.f, 180.f, 210.f, 240.f };
-                       _circle_path_interpolator(rsd, p, 240, endAngle[item->index%_ROTARY_SELECTOR_PAGE_ITEM_MAX], rsd->radius, rsd->radius, &coords->x, &coords->y, EINA_FALSE);
-                       new_a = 255*p;
+                       const float start_angle[] = {105.f, 120.f, 135.f, 150.f, 165.f, 180.f, 195.f, 210.f, 225.f, 240.f, 255.f };
+                       const float end_angle[] = {-60.f, -30.f, 0.f, 30.f, 60.f, 90.f, 120.f, 150.f, 180.f, 210.f, 240.f };
+                       _circle_path_interpolator(rsd, p, start_angle[item->index % _ROTARY_SELECTOR_PAGE_ITEM_MAX],
+                                                 end_angle[item->index%_ROTARY_SELECTOR_PAGE_ITEM_MAX],
+                                                 rsd->radius, rsd->radius, &coords->x, &coords->y, EINA_FALSE);
                        evas_object_move(button, item->coords.x, item->coords.y);
-                       evas_object_color_set(button, new_a, new_a, new_a, new_a);
+                       evas_object_color_set(button, 255, 255, 255, new_a);
                        evas_object_show(button);
                     }
                }
              i++;
           }
+
+        Evas_Coord x, y;
+        double px, py;
+        if (rsd->animation_direction)
+          {
+             //previous page button
+             if (!rsd->prev_page)
+               {
+                  rsd->prev_page = elm_layout_add(rsd->rotary_selector);
+                  elm_layout_theme_set(rsd->prev_page, "rotary_selector", "previous_page", "default");
+                  evas_object_smart_member_add(rsd->prev_page, rsd->rotary_selector);
+                  evas_object_show(rsd->prev_page);
+               }
+             evas_object_geometry_get(rsd->rotary_selector, &x, &y, NULL, NULL);
+             _circle_path_interpolator(rsd, p, 255.f, 270.f, rsd->radius, rsd->radius,
+                                       &px, &py, EINA_TRUE);
+             evas_object_move(rsd->prev_page, (Evas_Coord)(px + x + rsd->page_item_width * 0.5 + 6 ),
+                              (Evas_Coord)(py + y));
+             evas_object_color_set(rsd->prev_page, 255, 255, 255, new_a);
+          }
+        else
+          {
+             //next page button
+             if (!rsd->next_page)
+               {
+                  rsd->next_page = elm_layout_add(rsd->rotary_selector);
+                  elm_layout_theme_set(rsd->next_page, "rotary_selector", "next_page", "default");
+                  evas_object_smart_member_add(rsd->next_page, rsd->rotary_selector);
+                  evas_object_show(rsd->next_page);
+               }
+             evas_object_geometry_get(rsd->rotary_selector, &x, &y, NULL, NULL);
+             _circle_path_interpolator(rsd, p, 260.f, 245.f, rsd->radius, rsd->radius,
+                                       &px, &py, EINA_TRUE);
+             evas_object_move(rsd->next_page, (Evas_Coord)(px + x + rsd->page_item_width * 0.5 + 7),
+                              (Evas_Coord)(py + y - 13));
+             evas_object_color_set(rsd->next_page, 255, 255, 255, new_a);
+          }
      }
 
    if (p >= 1.0f)
@@ -2625,7 +2731,7 @@ _end_effect_animator_cb(void *data)
 
 // ----------------------------------------- new API --------------------------------------//
 static void
-_selector_update(Eext_Rotary_Selector_Data *rsd, Eina_Bool page_changed, Eina_Bool is_animation)
+_selector_update(Eext_Rotary_Selector_Data *rsd, Eina_Bool page_changed, Eina_Bool is_anim, Eina_Bool text_anim)
 {
    Evas_Object *edje = elm_layout_edje_get(rsd->rotary_selector);
    if (!edje)
@@ -2639,7 +2745,7 @@ _selector_update(Eext_Rotary_Selector_Data *rsd, Eina_Bool page_changed, Eina_Bo
 
    if (page_changed)
      {
-        if (rsd->selected_index%_ROTARY_SELECTOR_PAGE_ITEM_MAX == 0)
+        if (rsd->selected_index % _ROTARY_SELECTOR_PAGE_ITEM_MAX == 0)
           {
              edje_object_signal_emit(edje, "eext,rotate,360", "eext");
           }
@@ -2650,14 +2756,100 @@ _selector_update(Eext_Rotary_Selector_Data *rsd, Eina_Bool page_changed, Eina_Bo
      }
    else
      {
-        if (is_animation)
-          edje_object_signal_emit(edje, signals[rsd->selected_index%_ROTARY_SELECTOR_PAGE_ITEM_MAX], "eext");
+        if (is_anim)
+          edje_object_signal_emit(edje, signals[rsd->selected_index % _ROTARY_SELECTOR_PAGE_ITEM_MAX], "eext");
         else
-          edje_object_signal_emit(edje, signals[rsd->selected_index%_ROTARY_SELECTOR_PAGE_ITEM_MAX], "noanim");
+          edje_object_signal_emit(edje, signals[rsd->selected_index % _ROTARY_SELECTOR_PAGE_ITEM_MAX], "noanim");
      }
 
    if (!rsd->editing)
-     _selector_content_update(rsd);
+     {
+        if (text_anim)
+          {
+             if (rsd->content_animator)
+               {
+                  ecore_animator_del(rsd->content_animator);
+               }
+             rsd->content_animator_started = EINA_TRUE;
+             rsd->content_animator = ecore_animator_add(_content_hide_cb, rsd);
+             if (rsd->content_update_timer)
+               ecore_timer_del(rsd->content_update_timer);
+             rsd->content_update_timer = ecore_timer_add(_ROTARY_SELECTOR_PAGE_TEXT_ANIMATION_DURATION,
+                                                 _content_update_timer_cb, rsd);
+          }
+        else
+          {
+             _selector_content_update(rsd);
+          }
+     }
+}
+
+static Eina_Bool
+_content_show_hide_animate(Eext_Rotary_Selector_Data *rsd, Eina_Bool show)
+{
+   double p = 0.0f;
+   double v[4] = {_ROTARY_SELECTOR_CUBIC_BEZIER_P1_X,
+                  _ROTARY_SELECTOR_CUBIC_BEZIER_P1_Y,
+                  _ROTARY_SELECTOR_CUBIC_BEZIER_P2_X,
+                  _ROTARY_SELECTOR_CUBIC_BEZIER_P2_Y};
+   double dt;
+
+   if (rsd->content_animator_started)
+     {
+        rsd->content_animator_started = EINA_FALSE;
+        rsd->content_animator_start_time = ecore_time_unix_get();
+     }
+   dt = ecore_time_unix_get() - rsd->content_animator_start_time;
+   p = ecore_animator_pos_map_n(dt / _ROTARY_SELECTOR_PAGE_TEXT_ANIMATION_DURATION,
+                                ECORE_POS_MAP_CUBIC_BEZIER, 4, v);
+
+   if (p <= 1.0f)
+     {
+        Evas_Coord new_a;
+
+        if (show)
+          new_a = 255 * p;
+        else
+          new_a = 255 * (1 - p);
+        evas_object_color_set(elm_object_part_content_get(rsd->rotary_selector, "content"),
+                              new_a, new_a, new_a, new_a);
+     }
+
+   if (p >= 1.0f)
+     {
+        rsd->content_animator_start_time = 0.0f;
+        rsd->content_animator = NULL;
+
+        return ECORE_CALLBACK_CANCEL;
+     }
+   return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool
+_content_hide_cb(void *data)
+{
+   return _content_show_hide_animate(data, EINA_FALSE);
+}
+
+static Eina_Bool
+_content_show_cb(void *data)
+{
+   return _content_show_hide_animate(data, EINA_TRUE);
+}
+
+static Eina_Bool
+_content_update_timer_cb(void *data)
+{
+   Eext_Rotary_Selector_Data *rsd = data;
+
+   _selector_content_update(data);
+   rsd->content_animator_started = EINA_TRUE;
+   if (rsd->content_animator)
+     {
+        ecore_animator_del(rsd->content_animator);
+     }
+   rsd->content_animator = ecore_animator_add(_content_show_cb, data);
+   return ECORE_CALLBACK_CANCEL;
 }
 
 static void
@@ -4031,11 +4223,11 @@ _accessibility_item_btn_highlighted_cb(void *data, Evas_Object *obj, void *event
              _item_selected_signal_send(rsd, previous_item_index, rsd->selected_index);
              if (last_index < rsd->selected_index)
                {
-                  _selector_update(rsd, EINA_TRUE, EINA_TRUE);
+                  _selector_update(rsd, EINA_TRUE, EINA_TRUE, EINA_FALSE);
                }
              else
                {
-                  _selector_update(rsd, EINA_FALSE, EINA_TRUE);
+                  _selector_update(rsd, EINA_FALSE, EINA_TRUE, EINA_FALSE);
                }
              evas_object_smart_callback_call(rsd->rotary_selector, "item,selected", (void*)_item_get(rsd, rsd->selected_index));
           }
@@ -4048,11 +4240,11 @@ _accessibility_item_btn_highlighted_cb(void *data, Evas_Object *obj, void *event
              _item_selected_signal_send(rsd, previous_item_index, rsd->selected_index);
              if (first_index > rsd->selected_index)
                {
-                  _selector_update(rsd, EINA_TRUE, EINA_TRUE);
+                  _selector_update(rsd, EINA_TRUE, EINA_TRUE, EINA_FALSE);
                }
              else
                {
-                  _selector_update(rsd, EINA_FALSE, EINA_TRUE);
+                  _selector_update(rsd, EINA_FALSE, EINA_TRUE, EINA_FALSE);
                }
              evas_object_smart_callback_call(rsd->rotary_selector, "item,selected", (void*)_item_get(rsd, rsd->selected_index));
           }
@@ -4186,7 +4378,7 @@ _accessibility_item_gesutre_cb(void *data, Elm_Atspi_Gesture_Info gesture_info,
             {
                rsd->selected_index = item->index - 1;
                _page_animation_run(rsd, EINA_FALSE);
-               _selector_update(rsd, EINA_TRUE, EINA_TRUE);
+               _selector_update(rsd, EINA_TRUE, EINA_TRUE, EINA_TRUE);
                Eext_Rotary_Selector_Item *_item = _item_get(rsd, rsd->selected_index);
                if (_item)
                  {
@@ -4200,7 +4392,7 @@ _accessibility_item_gesutre_cb(void *data, Elm_Atspi_Gesture_Info gesture_info,
             {
                rsd->selected_index = item->index + 1;
                _page_animation_run(rsd, EINA_TRUE);
-               _selector_update(rsd, EINA_TRUE, EINA_TRUE);
+               _selector_update(rsd, EINA_TRUE, EINA_TRUE, EINA_TRUE);
                Eext_Rotary_Selector_Item *_item = _item_get(rsd, rsd->selected_index);
                if (_item)
                  {