Showing posts with label ontouchlistener. Show all posts
Showing posts with label ontouchlistener. Show all posts

Sunday, August 20, 2017

Rotate android layout view about its center using touch listener

Leave a Comment

Here is how my set up to rotate looks.

enter image description here

I am listening for action down and move on the rotation icon, trying to calculate the angle of rotation and applying that angle of rotation to entire layout encapsulating the edittext. The applied rotation has to be about the center of encapsulating relative layout.

Here is how I am trying to achieve this, in the touchListener for rotation icon.

if(v == ivRotateSticker){           //TODO grab xc and yc using (top and bottom)/2 and (left and right)/2 to grab center of sticker after each rotation         final float x = event.getX();         final float y = event.getY();         rlTextStickerLayout.getGlobalVisibleRect(myViewRect);         xc = myViewRect.width()/2;         yc = myViewRect.height()/2;          dx = scaleReceiver.getWidth() - myViewRect.width();         dy = scaleReceiver.getHeight() - myViewRect.height();          leftBound = scaleReceiver.getX();         topBound = scaleReceiver.getY();          switch (event.getAction()){              case MotionEvent.ACTION_DOWN:                 mViewAngle = rlTextStickerLayout.getRotation();                 mPrevAngle = Math.toDegrees(Math.atan2(x - xc, yc - y));                  break;              case MotionEvent.ACTION_MOVE:                  Log.d("EventRegistered", " " + event.getRawX() + "--" + dx + " -- " + dy);                  mCurrAngle = Math.toDegrees(Math.atan2(x - xc, yc - y));                 if (x >= leftBound && y >= topBound && x <= dx && y <= dy) {                     float rot = (float) (mViewAngle + mCurrAngle - mPrevAngle);                     rlTextStickerLayout.setRotation((float) (mViewAngle + mCurrAngle - mPrevAngle));                     Log.d("stickerRotation"," "+rot);                 }                 break;          }          return true;      } 

But the resulting rotation is glitchy and not as desired smooth. Also, if I move the sticker to a different location, how do I update the new center for rotation, as rotation after moving the sticker dramatically changes the center of rotation. How can I achieve a far more smooth rotation?

2 Answers

Answers 1

  1. View's rotation to be animated to the specified values (90, 180, 270) in 1000ms:

    view.animate().rotation(90f).setDuration(1000).start(); view.animate().rotation(180f).setDuration(1000).start(); view.animate().rotation(270f).setDuration(1000).start();

  2. Using this library you can rotate whole view hierarchy https://github.com/rongi/rotate-layout

Answers 2

I think this library will help you a lot.

https://github.com/kencheung4/android-StickerView

its smooth and easy.

Read More

Monday, April 4, 2016

Using BottomSheetBehavior with a inner CoordinatorLayout

Leave a Comment

The design support library v. 23.2 introduced BottomSheetBehavior, which allows childs of a coordinator to act as bottom sheets (views draggable from the bottom of the screen).

What I’d like to do is to have, as a bottom sheet view, the following view (the typical coordinator + collapsing stuff):

<CoordinatorLayout     app:layout_behavior=“@string/bottom_sheet_behavior”>     <AppBarLayout>         <CollapsingToolbarLayout>            <ImageView />         </CollapsingToolbarLayout>     </AppBarLayout>      <NestedScrollView>         <LinearLayout>             < Content ... />         </LinearLayout>     </NestedScrollView>  </CoordinatorLayout> 

Unfortunately, bottom sheet views should implement nested scrolling, or they won’t get scroll events. If you try with a main activity and then load this view as a bottom sheet, you’ll see that scroll events only act on the “sheet” of paper, with some strange behavior, as you can see if you keep reading.

I am pretty sure that this can be handled by subclassing CoordinatorLayout, or even better by subclassing BottomSheetBehavior. Do you have any hint?

Some thoughts

  • requestDisallowInterceptTouchEvent() should be used, to steal events from the parent in some conditions:

    • when the AppBarLayout offset is > 0
    • when the AppBarLayout offset is == 0, but we are scrolling up (think about it for a second and you’ll see)
  • the first condition can be obtained by setting an OnOffsetChanged to the inner app bar;

  • the second requires some event handling, for example:

    switch (MotionEventCompat.getActionMasked(event)) {     case MotionEvent.ACTION_DOWN:         startY = event.getY();         lastY = startY;         userIsScrollingUp = false;         break;     case MotionEvent.ACTION_CANCEL:     case MotionEvent.ACTION_UP:         userIsScrollingUp = false;         break;     case MotionEvent.ACTION_MOVE:         lastY = event.getY();         float yDeltaTotal = startY - lastY;         if (yDeltaTotal > touchSlop) { // Moving the finger up.             userIsScrollingUp = true;         }         break; } 

Issues

Needless to say, I can’t make this work right now. I am not able to catch the events when the conditions are met, and not catch them in other cases. In the image below you can see what happens with a standard CoordinatorLayout:

  • The sheet is dismissed if you scroll down on the appbar, but not if you scroll down on the nested content. It seems that nested scroll events are not propagated to the Coordinator behavior;

  • There is also a problem with the inner appbar: the nested scroll content does not follow the appbar when it is being collapsed..

enter image description here

I have setup a sample project on github that shows these issues.

Just to be clear, desired behavior is:

  • Correct behavior of appbars/scroll views inside the sheet;

  • When sheet is expanded, it can collapse on scroll down, but only if the inner appbar is fully expanded too. Right now it does collapse with no regards to the appbar state, and only if you drag the appbar;

  • When sheet is collapsed, scroll up gestures will expand it (with no effect on the inner appbar).

An example from the contacts app (which probably does not use BottomSheetBehavior, but this is what I want):

enter image description here

1 Answers

Answers 1

The layout for the full screen of appbar layout is as follows:-

<android.support.design.widget.AppBarLayout     android:id="@+id/appbar"     android:layout_width="match_parent"     android:layout_height="@dimen/detail_backdrop_height"     android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"     android:fitsSystemWindows="true">      <android.support.design.widget.CollapsingToolbarLayout         android:id="@+id/collapsing_toolbar"         android:layout_width="match_parent"         android:layout_height="match_parent"         app:layout_scrollFlags="scroll|exitUntilCollapsed"         android:fitsSystemWindows="true"         app:contentScrim="?attr/colorPrimary"         app:expandedTitleMarginStart="48dp"         app:expandedTitleMarginEnd="64dp">          <ImageView             android:id="@+id/backdrop"             android:layout_width="match_parent"             android:layout_height="match_parent"             android:scaleType="centerCrop"             android:fitsSystemWindows="true"             app:layout_collapseMode="parallax" />          <android.support.v7.widget.Toolbar             android:id="@+id/toolbar"             android:layout_width="match_parent"             android:layout_height="?attr/actionBarSize"             app:popupTheme="@style/ThemeOverlay.AppCompat.Light"             app:layout_collapseMode="pin" />      </android.support.design.widget.CollapsingToolbarLayout>  </android.support.design.widget.AppBarLayout>  <android.support.v4.widget.NestedScrollView     android:layout_width="match_parent"     android:layout_height="match_parent"     app:layout_behavior="@string/appbar_scrolling_view_behavior">      <LinearLayout         android:layout_width="match_parent"         android:layout_height="match_parent"         android:orientation="vertical"         android:paddingTop="24dp">          <android.support.v7.widget.CardView             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:layout_margin="@dimen/card_margin">              <LinearLayout                 style="@style/Widget.CardContent"                 android:layout_width="match_parent"                 android:layout_height="wrap_content">                  <TextView                     android:layout_width="match_parent"                     android:layout_height="wrap_content"                     android:text="Info"                     android:textAppearance="@style/TextAppearance.AppCompat.Title" />                  <TextView                     android:layout_width="match_parent"                     android:layout_height="wrap_content"                     android:text="@string/cheese_ipsum" />              </LinearLayout>          </android.support.v7.widget.CardView>          <android.support.v7.widget.CardView             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:layout_marginBottom="@dimen/card_margin"             android:layout_marginLeft="@dimen/card_margin"             android:layout_marginRight="@dimen/card_margin">              <LinearLayout                 style="@style/Widget.CardContent"                 android:layout_width="match_parent"                 android:layout_height="wrap_content">                  <TextView                     android:layout_width="match_parent"                     android:layout_height="wrap_content"                     android:text="Friends"                     android:textAppearance="@style/TextAppearance.AppCompat.Title" />                  <TextView                     android:layout_width="match_parent"                     android:layout_height="wrap_content"                     android:text="@string/cheese_ipsum" />              </LinearLayout>          </android.support.v7.widget.CardView>          <android.support.v7.widget.CardView             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:layout_marginBottom="@dimen/card_margin"             android:layout_marginLeft="@dimen/card_margin"             android:layout_marginRight="@dimen/card_margin">              <LinearLayout                 style="@style/Widget.CardContent"                 android:layout_width="match_parent"                 android:layout_height="wrap_content">                  <TextView                     android:layout_width="match_parent"                     android:layout_height="wrap_content"                     android:text="Related"                     android:textAppearance="@style/TextAppearance.AppCompat.Title" />                  <TextView                     android:layout_width="match_parent"                     android:layout_height="wrap_content"                     android:text="@string/cheese_ipsum" />              </LinearLayout>          </android.support.v7.widget.CardView>      </LinearLayout>  </android.support.v4.widget.NestedScrollView>  <android.support.design.widget.FloatingActionButton     android:layout_height="wrap_content"     android:layout_width="wrap_content"     app:layout_anchor="@id/appbar"     app:layout_anchorGravity="bottom|right|end"     android:src="@drawable/ic_discuss"     android:layout_margin="@dimen/fab_margin"     android:clickable="true"/> 

and after that you should implements AppBarLayout.OnOffsetChangedListener in your class and set offset of screen.

Read More