Showing posts with label ontouchevent. Show all posts
Showing posts with label ontouchevent. Show all posts

Saturday, October 13, 2018

Select multiple bitmaps using OnTouchEvent

Leave a Comment

I am developing a card based game, in which user can select one or multiple cards from its deck and replace the cards with cards of other decks. I am using onTouchEvent to detect whether the user has selected any bitmap or not and replace that Bitmap with Bitmap of other deck. However OnTouchEvent only allows me to select one bitmap at a time. How can I select multiple bitmaps from my deck? Also I want to know if there is any better approach to swap bitmaps other than the one I used.

Thread Class:

 class MySurfaceViewThread:BaseThread {     private MySurfaceView mysurfaceview;     private ISurfaceHolder myThreadSurfaceHolder;     bool running;      public MySurfaceViewThread(ISurfaceHolder paramSurfaceHolder, MySurfaceView paramSurfaceView)     {         mysurfaceview = paramSurfaceView;         myThreadSurfaceHolder = paramSurfaceHolder;      }     public override void RunThread()     {          Canvas c;         while (running)         {             c = null;             try             {               c = myThreadSurfaceHolder.LockCanvas(null);                  mysurfaceview.Render(c);            //  mysurfaceview.PostInvalidate();              }             catch (Exception ex)             {                 System.Diagnostics.Debug.WriteLine(ex.ToString());             }             finally             {                 if (c != null)                 {                     myThreadSurfaceHolder.UnlockCanvasAndPost(c);                    }              //   running = false;             }          }      }     public override void SetRunning(bool paramBoolean)     {         running = paramBoolean;     } } 

OnTouchEvent:

 public override bool OnTouchEvent(MotionEvent e)     {         Log.Debug(Tag, "Inside" + System.Reflection.MethodBase.GetCurrentMethod().Name + "Method");         float lasttouched_X, lasttouched_Y;         Cards localcard;         int index=-1;          //switch (e.Action) {          //    case MotionEventActions.Up: Log.Info(Tag, "Up Event is Triggered");         //        break;         //    case MotionEventActions.Move: Log.Info(Tag, "Move Event is Triggered");         //        break;         //    case MotionEventActions.Down: Log.Info(Tag, "Down Event is triggered");          //        break;          //}         MotionEventActions action = e.Action;         if (e.Action == MotionEventActions.Down || e.Action== MotionEventActions.Move)         {             Log.Info(Tag, "Down Event is triggered");             lasttouched_X = e.GetX();             lasttouched_Y = e.GetY();             if (TouchedCard == null)             {                 index = CardTouched((int)lasttouched_X, (int)lasttouched_Y);                 TouchedCard = MainPlayer.getCard(index);                 cardindex = index;             }             else             {                 if (TouchedCard != null && ((lasttouched_X >= DiscardDeck_CurrentX && lasttouched_X < (DiscardDeck_CurrentX + DiscardedDeck.getCard().Image.Width)) && (lasttouched_Y >= DiscardDeck_CurrentY && lasttouched_Y < (DiscardDeck_CurrentY + DiscardedDeck.getCard().Image.Width))))                 {                     ReplacedCard = DiscardedDeck.getCard();                 }                  if (ReplacedCard != null)                     SwapCards(ReplacedCard, MainPlayer, cardindex);             }          }         return true;     }      private void SwapCards(Cards replacedCard, Deck mainPlayer, int index)     {          Cards temp = mainPlayer.getCard(index);         mainPlayer.SetCurrentCard(replacedCard, index);         DiscardedDeck.SetCurrentCard(temp, DiscardedDeck.CardsLeft()-1);         TouchedCard = null;         cardindex = -1;      }      private int CardTouched(int lasttouched_X, int lasttouched_Y)     {         int index = 0;         Cards localcard = null;         while (index < MainPlayer.CardsLeft())         {             localcard = MainPlayer.getCard(index);             if (lasttouched_X >= localcard.current_X && lasttouched_X < (localcard.current_X + localcard.Image.Width) && (lasttouched_Y>=localcard.current_Y && lasttouched_Y<(localcard.current_Y+localcard.Image.Width)))                 return index;             index++;         }          return -1;     } 

0 Answers

Read More

Wednesday, January 24, 2018

From an imageview touch point can you resize a MAT to get that points color?

Leave a Comment

In landscape orientation, I using myImageView.setImageBitmap(myBitmap) and using an ontouch listener to getX and getY and adjust for location of myImageView (same as getRawX and getRawY). I then use bitmapToMat to build a MAT to process the image more with OpenCV. I found two resizing scenarios where the onTouch location will draw a circle exactly where I touched but at times the location will be outside the Mat and cause a NPE and fail during processing.

Scenario 1: resize(myImageView.getWidth(), myImageView.getHeight())

Scenario 2: resize(myImageView.getHeight(), myImageView.getWidth()) and

x = x(myImage.getHeight()/myImageView.getWidth())  y = y(myImage.getWidth()/myImageView.getHeight()) 

If I dont change the x,y I can click everywhere in image w/o the NPE but the circle drawn is nowhere near where I touched.

After processing I matToBitmap(myMAT, newBitmap) and myImageView.setImageBitmap(newBitmap) .

I am obviously missing something but is there there a simple way to get the touch location and use that location in a MAT? Any help would be awesome!

1 Answers

Answers 1

You have to offset the touched coordinates as the view might be bigger or smaller than the mat. Something like this should work

private Scalar getColor(View v, MotionEvent event){     int cols = yourMat.cols();     int rows = yourMat.rows();      int xOffset = (v.getWidth() - cols) / 2;     int yOffset = (v.getHeight() - rows) / 2;      int x = (int)event.getX() - xOffset;     int y = (int)event.getY() - yOffset;    Point  touchedPoint    = new Point(x,y);    Rect   touchedRect = new Rect();      touchedRect.x = (x>4) ? x-4 : 0;     touchedRect.y = (y>4) ? y-4 : 0;      touchedRect.width = (x+4 < cols) ? x + 4 - touchedRect.x : cols - touchedRect.x;     touchedRect.height = (y+4 < rows) ? y + 4 - touchedRect.y : rows - touchedRect.y;      Mat touchedRegionRgba = yourMat.submat(touchedRect);      Scalar mBlobColor = Core.mean(touchedRegionRgba);      touchedRegionRgba.release();      return mBlobColor; } 
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