redraw bitmap on the android canvas - android

In my app, I want to switch a bitmap image from one to another when I touch on that image. I keep getting NULLPOINTEREXCEPTION whenever I touch the image.
Is there any method that allows to switch from a bitmap to other bitmap?
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
this.cVas = canvas;
for(int i = 0; i < BSIZE; i++) {
for(int j = 0; j < BSIZE; j++) {
gameBoard[i][j] = new Cell(i*wCell, j*wCell+hCell);
if(gameBoard[i][j].getBitmap() == null) {
gameBoard[i][j].setBitmap(b3);
}
/*if(gameBoard[i][j].getTouch()) {
gameBoard[i][j].setBitmap(b4);
}else{
gameBoard[i][j].setBitmap(b3);
}*/
gameBoard[i][j].drawCell(canvas);
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() != MotionEvent.ACTION_DOWN) {
return super.onTouchEvent(event);
}
// Get the Cell's position.
selX = (int)((event.getX()) / wCell);
selY = (int)((event.getY() - hCell) / wCell);
if( selX > BSIZE || selY > BSIZE || selY < 0) {
return false;
}
else {
Log.d(TAG, "selX: " + selX + " selY: " + selY);
cellSelection(selX, selY);
}
return true;
}
// Redraw the image (switch to other bitmap).
private void cellSelection( int x, int y) {
if(gameBoard[x][y].getTouch()) {
gameBoard[x][y].setTouch(false);
gameBoard[x][y].setBitmap(b3);
} else {
gameBoard[x][y].setTouch(true);
gameBoard[x][y].setBitmap(b4);
}
gameBoard[x][y].drawCell(cVas);
invalidate();
}

Related

Android Google Maps: Disable Scroll on Zoom

I tried by creating custom class for mapview but it is not working. Can any one suggest me an approach. How to disable scroll when user tries to zoom. Scroll should be enable when zoom is not performed.
I Have solved the problem using below code.
Create variables in Class
private ScaleGestureDetector gestureDetector;
private long lastZoomTime = 0;
private float lastSpan = -1;
private long firstClick=0;
private long lastClick;
GoogleMap mMap;
In OnMapReady method add below code:
mMap = googleMap;
gestureDetector = new ScaleGestureDetector(getApplicationContext(), new ScaleGestureDetector.OnScaleGestureListener() {
#Override
public boolean onScale(ScaleGestureDetector detector) {
Log.i("onScale ", " onScale ");
if (lastSpan == -1) {
lastSpan = detector.getCurrentSpan();
}
if (detector.getEventTime() - lastZoomTime >= 50) {
lastZoomTime = detector.getEventTime();
mMap.animateCamera(CameraUpdateFactory.zoomBy(getZoomValue(detector.getCurrentSpan(), lastSpan)), 50, null);
lastSpan = detector.getCurrentSpan();
}
return false;
}
#Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
lastSpan = -1;
return true;
}
#Override
public void onScaleEnd(ScaleGestureDetector detector) {
lastSpan = -1;
}
});
Add Below Methods in class
private float getZoomValue(float currentSpan, float lastSpan) {
Log.i("ongetZoomValue ", " getZoomValue ");
double value = (Math.log(currentSpan / lastSpan) / Math.log(1.55d));
return (float) value;
}
public boolean dispatchTouchEvent(MotionEvent ev) {
//Log.i("on dispatchTouchEvent ", " dispatchTouchEvent ");
switch (ev.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_POINTER_DOWN:
fingers = fingers + 1;
break;
case MotionEvent.ACTION_POINTER_UP:
fingers = fingers - 1;
break;
case MotionEvent.ACTION_UP:
fingers = 0;
break;
case MotionEvent.ACTION_DOWN:
if (firstClick != 0 && System.currentTimeMillis() - firstClick > 300) {
Log.i("on count=0", " count=0 ");
count = 0;
}
count++;
if (count == 1) {
Log.i("on count ", " count=1 ");
firstClick = System.currentTimeMillis();
} else if (count == 2) {
Log.i("on count ", " count=2 ");
lastClick = System.currentTimeMillis();
if (lastClick - firstClick < 300) {
CameraUpdate getzoom = CameraUpdateFactory.zoomIn();
mMap.animateCamera(getzoom, 400, null);
Log.i("on double click ", " event ");
}
}
fingers=1;
break;
}
if (fingers >1) {
//Log.i("2fingersaction ", "2fingersaction ");
mMap.getUiSettings().setScrollGesturesEnabled(false);
//mMap.getUiSettings().setRotateGesturesEnabled(false); // disableScrolling()
}
else if (fingers < 1 )
{
//Log.i("onefinger ", "onefinger ");
mMap.getUiSettings().setScrollGesturesEnabled(true);
// enableScrolling();
}
if (fingers > 1) {
//Log.i("double if condition ", "doubleifcondition ");
return gestureDetector.onTouchEvent(ev);
} else
return super.dispatchTouchEvent(ev);
}

How to add multiple pin marker on image dyanamically

I want to put marker on image with below functionality
-Dynamically adding multiple markers on image with zoom and scroll functionality on image.
-Blink animation on marker after added on image.
-Marker can be click-able and drag & drop on image.
-Marker's x & y position on image to sync same with other devices
I have used https://github.com/davemorrissey/subsampling-scale-image-view library
Java Code :
public class PinMarkerView extends SubsamplingScaleImageView implements View.OnTouchListener {
private PointF sPin;
private Bitmap pin;
private int resId;
public float vX;
public float vY;
private PointF vPrevious;
private PointF vStart;
private boolean drawing = false;
private boolean markerTouch = false;
private int strokeWidth;
private ArrayList<MapPins> allPins = new ArrayList<MapPins>();
private ArrayList<DrawPins> drawnPins = new ArrayList<DrawPins>();
public PinView(Context context) {
this(context, null);
}
public PinView(Context context, AttributeSet attr) {
super(context, attr);
// initialise();
}
public void setPin(PointF sPin, #DrawableRes int resid, String extras) {
MapPins mapPins = new MapPins();
mapPins.setPointF(sPin);
mapPins.setResId(resid);
mapPins.setExtrasData(extras);
mapPins.setX(sPin.x);
mapPins.setY(sPin.y);
allPins.add(mapPins);
//this.sPin = sPin;
// this.resId = resid;
initialise();
invalidate();
}
public PointF getPin() {
return sPin;
}
public Bitmap getMarker() {
return pin;
}
private void initialise() {
setOnTouchListener(this);
float density = getResources().getDisplayMetrics().densityDpi;
strokeWidth = (int) (density / 60f);
for (int i = 0; i < allPins.size(); i++) {
MapPins mapPins = allPins.get(i);
Bitmap localpin = BitmapFactory.decodeResource(this.getResources(), mapPins.getResId());
float w = (density / 100f) * localpin.getWidth();
float h = (density / 100f) * localpin.getHeight();
//pin = Bitmap.createScaledBitmap(pin, (int) w, (int) h, true);
pin = Bitmap.createScaledBitmap(localpin, localpin.getWidth(), localpin.getHeight(), true);
mapPins.setCreatedBitmap(pin);
allPins.set(i, mapPins);
//-------
}
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Don't draw pin before image is ready so it doesn't move around during setup.
if (!isReady()) {
return;
}
Paint paint = new Paint();
paint.setAntiAlias(true);
for (int i = 0; i < allPins.size(); i++) {
MapPins mapPins = allPins.get(i);
if (mapPins.getPointF() != null && mapPins.getCreatedBitmap() != null) {
PointF vPin = sourceToViewCoord(mapPins.getPointF());
vX = vPin.x - (mapPins.getCreatedBitmap().getWidth() / 2);
vY = vPin.y - mapPins.getCreatedBitmap().getHeight();
canvas.drawBitmap(mapPins.getCreatedBitmap(), vX, vY, paint);
}
}
}
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
setMaxScale(5f);
return false;
}
#Override
public boolean onTouchEvent(#NonNull MotionEvent event) {
/* if (isZoomEnabled()) {
return super.onTouchEvent(event);
}*/
boolean consumed = false;
int touchCount = event.getPointerCount();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_1_DOWN:
vStart = new PointF(event.getX(), event.getY());
vPrevious = new PointF(event.getX(), event.getY());
getPinIdByPoint(vStart, viewToSourceCoord(event.getX(), event.getY()));
handleActionDown((int) event.getX(), (int) event.getY());
break;
case MotionEvent.ACTION_POINTER_2_DOWN:
// Abort any current drawing, user is zooming
vStart = null;
vPrevious = null;
break;
case MotionEvent.ACTION_MOVE:
if (markerTouch) {
setPanEnabled(false);
PointF sCurrentF = viewToSourceCoord(event.getX(), event.getY());
PointF sCurrent = new PointF(sCurrentF.x, sCurrentF.y);
PointF sStart = vStart == null ? null : new PointF(viewToSourceCoord(vStart).x, viewToSourceCoord(vStart).y);
if (touchCount == 1 && vStart != null) {
float vDX = Math.abs(event.getX() - vPrevious.x);
float vDY = Math.abs(event.getY() - vPrevious.y);
if (vDX >= strokeWidth * 5 || vDY >= strokeWidth * 5) {
if (sPin == null) {
sPin = sStart;
}
sPin = sCurrent;
vPrevious.x = event.getX();
vPrevious.y = event.getY();
drawing = true;
}
consumed = true;
invalidate();
} else if (touchCount == 1) {
// Consume all one touch drags to prevent odd panning effects handled by the superclass.
consumed = true;
}
} else {
return super.onTouchEvent(event);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
invalidate();
setPanEnabled(true);
drawing = false;
markerTouch = false;
vPrevious = null;
vStart = null;
}
// Use parent to handle pinch and two-finger pan.
return consumed || super.onTouchEvent(event);
}
public void handleActionDown(int eventX, int eventY) {
if (eventX >= (sPin.x - pin.getWidth()) && (eventX <= (sPin.x + pin.getWidth()))) {
if (eventY >= (sPin.y - pin.getHeight()) && (sPin.y <= (sPin.y + pin.getHeight()))) {
markerTouch = true;
} else {
markerTouch = false;
}
} else {
markerTouch = false;
}
}
public int getPinIdByPoint(PointF tappedCoordinate, PointF deeplinkCoordinate) {
for (int i = allPins.size() - 1; i >= 0; i--) {
MapPins dPin = allPins.get(i);
int blockWidth = dPin.getCreatedBitmap().getWidth();
int blockHeight = dPin.getCreatedBitmap().getHeight();
int deeplinkX = (int) (deeplinkCoordinate.x - (dPin.getCreatedBitmap().getWidth() / 2));
int deeplinkY = (int) (deeplinkCoordinate.y - dPin.getCreatedBitmap().getHeight());
// center coordinate -/+ blockWidth actually sets touchable area to 2x icon size
if (tappedCoordinate.x >= deeplinkX - blockWidth && tappedCoordinate.x <= deeplinkX + blockWidth &&
tappedCoordinate.y >= deeplinkY - blockHeight && tappedCoordinate.y <= deeplinkY + blockHeight) {
sPin = dPin.getPointF();
pin = dPin.getCreatedBitmap();
return dPin.getId();
}
}
return -1; //negative no means no pin selected
}
}
Currently, I am able to add multiple marker, but I am facing issue of marker click and dragging on image.

Detect touch outside of View

I have a custom View and I wonder, is there any chace that I could detect if something outside of my View is clicked. It MUST be in the View class, or else it can not work as I intended it to!
Full file: https://github.com/Nicba1010/AndroidLibrary/blob/master/src/com/nicba1010/utils/views/PieChartView.java
OnTouchEvent(so you know I did something)
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
selected = null;
invalidate();
return true;
}
double deltaX = event.getX() - rect.width() / 2 - rect.left;
double deltaY = -(event.getY() - rect.height() / 2 - rect.top);
double fromMid = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
boolean inCircle = fromMid < (rectSelect.bottom / 2);
if (inCircle) {
double angleInDegrees = getPositionOnCircumference(deltaX, deltaY);
float percentage = (float) (angleInDegrees / 360f);
float totalPerc = 0;
int index = -1, i = 0;
for (PieChartSlice e : slices) {
if (percentage > totalPerc) {
index = i;
} else if (percentage < totalPerc) {
break;
}
totalPerc += e.getPercentage();
i++;
}
if (index == -1) {
Toast.makeText(getContext(), "ERROR", Toast.LENGTH_LONG).show();
} else {
final PieChartSlice tmp = slices.get(index);
addScaleTask(rect, 500, 0.9f, new Runnable() {
#Override
public void run() {
selected = tmp;
}
});
selected = slices.get(index);
invalidate();
Toast.makeText(getContext(), selected.getName(),
Toast.LENGTH_SHORT).show();
onSliceSelectedListener.onSliceSelected(this, selected);
}
} else {
if (selected != null) {
addScaleTask(rect, 500, 1f, new Runnable() {
#Override
public void run() {
selected = null;
}
});
invalidate();
}
}
return super.onTouchEvent(event);
}
View has the getHitRect(Rect) method. You can use to retrieve it hit rect of this view and you can use this rect to check it the MotionEvent it is inside it. For instance
Rect rect = new Rect();
getHitRect(rect);
if (rect.contains((int) event.getX(), (int) event.getY()) {
}

Select Text and show meaning as pop up in MUPDF

I am using MUPDF Library and i added features for manual zoom in, zoom out , rating, setting brightness. Now i am doing with long press the highlighted text and i have to show the meaning from my database. I am trying to do with two things one is clipboard or emulateShiftHeld the below feature is for only android ICS and JellyBean. Can any body suggest on whether any one thing will work for this feature what i am trying. Because on Long Press i can't able to capture the text. Suggestions will be helpful.
This id my MUPDF Activity:
public void createUI(Bundle savedInstanceState) {
if (core == null)
return;
// Now create the UI.
// First create the document view making use of the ReaderView's internal
// gesture recognition
mDocView = new ReaderView(this) {
private boolean showButtonsDisabled;
public void onLongPress(MotionEvent e) {
selectAndCopyText();
//mDocView.getSelectedItem();
//SelectText(mDocView);
/*emulateShiftHeld(layout);
clipboard =
(ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
clipboard.setText(clipboard.getText().toString());
//layout.findAll(clipboard.getText().toString());
//ClipMan.setPrimaryClip(clipboard);
//String s = (String) clipboard.getText();
//System.out.println("fsfasd"+ s);
CharSequence pasteData="";
ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);
pasteData = item.getText();
System.out.println("fsf"+pasteData);*/
//ClipData data = ClipData.newPlainText("", "");
///System.out.println("sdf" + data);
//copyClipboard();
}
#SuppressWarnings("deprecation")
public void selectAndCopyText() {
try {
Method m = WebView.class.getMethod("emulateShiftHeld", Boolean.TYPE);
m.invoke(mDocView, false);
} catch (Exception e) {
e.printStackTrace();
// fallback
KeyEvent shiftPressEvent = new KeyEvent(0,0,
KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_SHIFT_LEFT,0,0);
shiftPressEvent.dispatch(this);
}
}
public void startTextSelection() {
try {
WebView.class.getMethod("selectText").invoke(this);
} catch (Exception e) {
try {
WebView.class.getMethod("emulateShiftHeld").invoke(this);
} catch (Exception e1) {
KeyEvent shiftPressEvent = new KeyEvent(0, 0,
KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_SHIFT_LEFT, 0, 0);
shiftPressEvent.dispatch(this);
Toast.makeText(getContext(), R.string.app_name, Toast.LENGTH_LONG).show();
}
}
}
// Stick the document view and the buttons overlay into a parent view
//Embedding my reader view to webview
layout = new WebView(this);
layout.addView(mDocView);
layout.addView(mButtonsView);
layout.setBackgroundResource(R.drawable.tiled_background);
//layout.setBackgroundResource(R.color.canvas);
setContentView(layout);
}
This is my Reader View:
public class ReaderView extends AdapterView<Adapter>
implements GestureDetector.OnGestureListener,
ScaleGestureDetector.OnScaleGestureListener,
Runnable {
private static final int MOVING_DIAGONALLY = 0;
private static final int MOVING_LEFT = 1;
private static final int MOVING_RIGHT = 2;
private static final int MOVING_UP = 3;
private static final int MOVING_DOWN = 4;
private static final int FLING_MARGIN = 100;
private static final int GAP = 20;
private static final int SCROLL_SPEED = 2;
private static final float MIN_SCALE = 1.0f;
private static final float MAX_SCALE = 5.0f;
private Adapter mAdapter;
private int mCurrent; // Adapter's index for the current view
private boolean mResetLayout;
private final SparseArray<View>
mChildViews = new SparseArray<View>(3);
// Shadows the children of the adapter view
// but with more sensible indexing
private final LinkedList<View>
mViewCache = new LinkedList<View>();
private boolean mUserInteracting; // Whether the user is interacting
private boolean mScaling; // Whether the user is currently pinch zooming
private float mScale = 1.0f;
private int mXScroll; // Scroll amounts recorded from events.
private int mYScroll; // and then accounted for in onLayout
private final GestureDetector
mGestureDetector;
private final ScaleGestureDetector
mScaleGestureDetector;
private final Scroller mScroller;
private int mScrollerLastX;
private int mScrollerLastY;
private boolean mScrollDisabled;
public ReaderView(Context context) {
super(context);
mGestureDetector = new GestureDetector(this);
mScaleGestureDetector = new ScaleGestureDetector(context, this);
mScroller = new Scroller(context);
}
public ReaderView(Context context, AttributeSet attrs) {
super(context, attrs);
mGestureDetector = new GestureDetector(this);
mScaleGestureDetector = new ScaleGestureDetector(context, this);
mScroller = new Scroller(context);
}
public ReaderView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mGestureDetector = new GestureDetector(this);
mScaleGestureDetector = new ScaleGestureDetector(context, this);
mScroller = new Scroller(context);
}
public int getDisplayedViewIndex(ToggleButton bookmark_page, String index_from) {
if (index_from.equals("bookmark_button")) { System.out.println("View_if" + index_from);
bookmark_page.setBackgroundResource(R.drawable.top3hover);
} else { System.out.println("View_else" + index_from);
bookmark_page.setBackgroundResource(R.drawable.top3);
}
return mCurrent;
}
public void setDisplayedViewIndex(int i) {
if (0 <= i && i < mAdapter.getCount()) {
mCurrent = i;
onMoveToChild(i);
mResetLayout = true;
requestLayout();
}
}
public void moveToNext() {
View v = mChildViews.get(mCurrent+1);
if (v != null)
slideViewOntoScreen(v);
}
public void moveToPrevious() {
View v = mChildViews.get(mCurrent-1);
if (v != null)
slideViewOntoScreen(v);
}
public void resetupChildren() {
for (int i = 0; i < mChildViews.size(); i++)
onChildSetup(mChildViews.keyAt(i), mChildViews.valueAt(i));
}
protected void onChildSetup(int i, View v) {}
protected void onMoveToChild(int i) {}
protected void onSettle(View v) {};
protected void onUnsettle(View v) {};
protected void onNotInUse(View v) {};
public View getDisplayedView() {
return mChildViews.get(mCurrent);
}
public void run() {
if (!mScroller.isFinished()) {
mScroller.computeScrollOffset();
int x = mScroller.getCurrX();
int y = mScroller.getCurrY();
mXScroll += x - mScrollerLastX;
mYScroll += y - mScrollerLastY;
mScrollerLastX = x;
mScrollerLastY = y;
requestLayout();
post(this);
}
else if (!mUserInteracting) {
// End of an inertial scroll and the user is not interacting.
// The layout is stable
View v = mChildViews.get(mCurrent);
postSettle(v);
}
}
public boolean onDown(MotionEvent arg0) {
mScroller.forceFinished(true);
return true;
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
if (mScrollDisabled)
return true;
View v = mChildViews.get(mCurrent);
if (v != null) {
Rect bounds = getScrollBounds(v);
switch(directionOfTravel(velocityX, velocityY)) {
case MOVING_LEFT:
if (bounds.left >= 0) {
// Fling off to the left bring next view onto screen
View vl = mChildViews.get(mCurrent+1);
if (vl != null) {
slideViewOntoScreen(vl);
return true;
}
}
break;
case MOVING_RIGHT:
if (bounds.right <= 0) {
// Fling off to the right bring previous view onto screen
View vr = mChildViews.get(mCurrent-1);
if (vr != null) {
slideViewOntoScreen(vr);
return true;
}
}
break;
}
mScrollerLastX = mScrollerLastY = 0;
// If the page has been dragged out of bounds then we want to spring back
// nicely. fling jumps back into bounds instantly, so we don't want to use
// fling in that case. On the other hand, we don't want to forgo a fling
// just because of a slightly off-angle drag taking us out of bounds other
// than in the direction of the drag, so we test for out of bounds only
// in the direction of travel.
//
// Also don't fling if out of bounds in any direction by more than fling
// margin
Rect expandedBounds = new Rect(bounds);
expandedBounds.inset(-FLING_MARGIN, -FLING_MARGIN);
if(withinBoundsInDirectionOfTravel(bounds, velocityX, velocityY)
&& expandedBounds.contains(0, 0)) {
mScroller.fling(0, 0, (int)velocityX, (int)velocityY, bounds.left, bounds.right, bounds.top, bounds.bottom);
post(this);
}
}
return true;
}
public void onLongPress(MotionEvent e) {
}
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
if (!mScrollDisabled) {
mXScroll -= distanceX;
mYScroll -= distanceY;
requestLayout();
}
return true;
}
public void onShowPress(MotionEvent e) {
}
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
public boolean onScale(ScaleGestureDetector detector) {
float previousScale = mScale;
mScale = Math.min(Math.max(mScale * detector.getScaleFactor(), MIN_SCALE), MAX_SCALE);
float factor = mScale/previousScale;
View v = mChildViews.get(mCurrent);
if (v != null) {
// Work out the focus point relative to the view top left
int viewFocusX = (int)detector.getFocusX() - (v.getLeft() + mXScroll);
int viewFocusY = (int)detector.getFocusY() - (v.getTop() + mYScroll);
// Scroll to maintain the focus point
mXScroll += viewFocusX - viewFocusX * factor;
mYScroll += viewFocusY - viewFocusY * factor;
requestLayout();
}
return true;
}
public boolean onScaleBegin(ScaleGestureDetector detector) {
mScaling = true;
// Ignore any scroll amounts yet to be accounted for: the
// screen is not showing the effect of them, so they can
// only confuse the user
mXScroll = mYScroll = 0;
// Avoid jump at end of scaling by disabling scrolling
// until the next start of gesture
mScrollDisabled = true;
return true;
}
public void onScaleEnd(ScaleGestureDetector detector) {
mScaling = false;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
//mScaleGestureDetector.onTouchEvent(event);
if (!mScaling)
mGestureDetector.onTouchEvent(event);
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
mUserInteracting = true;
}
if (event.getActionMasked() == MotionEvent.ACTION_UP) {
mScrollDisabled = false;
mUserInteracting = false;
View v = mChildViews.get(mCurrent);
if (v != null) {
if (mScroller.isFinished()) {
// If, at the end of user interaction, there is no
// current inertial scroll in operation then animate
// the view onto screen if necessary
slideViewOntoScreen(v);
}
if (mScroller.isFinished()) {
// If still there is no inertial scroll in operation
// then the layout is stable
postSettle(v);
}
}
}
requestLayout();
return true;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int n = getChildCount();
for (int i = 0; i < n; i++)
measureView(getChildAt(i));
}
#Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
View cv = mChildViews.get(mCurrent);
Point cvOffset;
if (!mResetLayout) {
// Move to next or previous if current is sufficiently off center
if (cv != null) {
cvOffset = subScreenSizeOffset(cv);
// cv.getRight() may be out of date with the current scale
// so add left to the measured width for the correct position
if (cv.getLeft() + cv.getMeasuredWidth() + cvOffset.x + GAP/2 + mXScroll < getWidth()/2 && mCurrent + 1 < mAdapter.getCount()) {
postUnsettle(cv);
// post to invoke test for end of animation
// where we must set hq area for the new current view
post(this);
mCurrent++;
onMoveToChild(mCurrent);
}
if (cv.getLeft() - cvOffset.x - GAP/2 + mXScroll >= getWidth()/2 && mCurrent > 0) {
postUnsettle(cv);
// post to invoke test for end of animation
// where we must set hq area for the new current view
post(this);
mCurrent--;
onMoveToChild(mCurrent);
}
}
// Remove not needed children and hold them for reuse
int numChildren = mChildViews.size();
int childIndices[] = new int[numChildren];
for (int i = 0; i < numChildren; i++)
childIndices[i] = mChildViews.keyAt(i);
for (int i = 0; i < numChildren; i++) {
int ai = childIndices[i];
if (ai < mCurrent - 1 || ai > mCurrent + 1) {
View v = mChildViews.get(ai);
onNotInUse(v);
mViewCache.add(v);
removeViewInLayout(v);
mChildViews.remove(ai);
}
}
} else {
mResetLayout = false;
mXScroll = mYScroll = 0;
// Remove all children and hold them for reuse
int numChildren = mChildViews.size();
for (int i = 0; i < numChildren; i++) {
View v = mChildViews.valueAt(i);
onNotInUse(v);
mViewCache.add(v);
removeViewInLayout(v);
}
mChildViews.clear();
// post to ensure generation of hq area
post(this);
}
// Ensure current view is present
int cvLeft, cvRight, cvTop, cvBottom;
boolean notPresent = (mChildViews.get(mCurrent) == null);
cv = getOrCreateChild(mCurrent);
// When the view is sub-screen-size in either dimension we
// offset it to center within the screen area, and to keep
// the views spaced out
cvOffset = subScreenSizeOffset(cv);
if (notPresent) {
//Main item not already present. Just place it top left
cvLeft = cvOffset.x;
cvTop = cvOffset.y;
} else {
// Main item already present. Adjust by scroll offsets
cvLeft = cv.getLeft() + mXScroll;
cvTop = cv.getTop() + mYScroll;
}
// Scroll values have been accounted for
mXScroll = mYScroll = 0;
cvRight = cvLeft + cv.getMeasuredWidth();
cvBottom = cvTop + cv.getMeasuredHeight();
if (!mUserInteracting && mScroller.isFinished()) {
Point corr = getCorrection(getScrollBounds(cvLeft, cvTop, cvRight, cvBottom));
cvRight += corr.x;
cvLeft += corr.x;
cvTop += corr.y;
cvBottom += corr.y;
} else if (cv.getMeasuredHeight() <= getHeight()) {
// When the current view is as small as the screen in height, clamp
// it vertically
Point corr = getCorrection(getScrollBounds(cvLeft, cvTop, cvRight, cvBottom));
cvTop += corr.y;
cvBottom += corr.y;
}
cv.layout(cvLeft, cvTop, cvRight, cvBottom);
if (mCurrent > 0) {
View lv = getOrCreateChild(mCurrent - 1);
Point leftOffset = subScreenSizeOffset(lv);
int gap = leftOffset.x + GAP + cvOffset.x;
lv.layout(cvLeft - lv.getMeasuredWidth() - gap,
(cvBottom + cvTop - lv.getMeasuredHeight())/2,
cvLeft - gap,
(cvBottom + cvTop + lv.getMeasuredHeight())/2);
}
if (mCurrent + 1 < mAdapter.getCount()) {
View rv = getOrCreateChild(mCurrent + 1);
Point rightOffset = subScreenSizeOffset(rv);
int gap = cvOffset.x + GAP + rightOffset.x;
rv.layout(cvRight + gap,
(cvBottom + cvTop - rv.getMeasuredHeight())/2,
cvRight + rv.getMeasuredWidth() + gap,
(cvBottom + cvTop + rv.getMeasuredHeight())/2);
}
invalidate();
}
#Override
public Adapter getAdapter() {
return mAdapter;
}
#Override
public View getSelectedView() {
throw new UnsupportedOperationException("Not supported");
}
#Override
public void setAdapter(Adapter adapter) {
mAdapter = adapter;
mChildViews.clear();
removeAllViewsInLayout();
requestLayout();
}
#Override
public void setSelection(int arg0) {
throw new UnsupportedOperationException("Not supported");
}
private View getCached() {
if (mViewCache.size() == 0)
return null;
else
return mViewCache.removeFirst();
}
private View getOrCreateChild(int i) {
View v = mChildViews.get(i);
if (v == null) {
v = mAdapter.getView(i, getCached(), this);
addAndMeasureChild(i, v);
}
onChildSetup(i, v);
return v;
}
private void addAndMeasureChild(int i, View v) {
LayoutParams params = v.getLayoutParams();
if (params == null) {
params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
addViewInLayout(v, 0, params, true);
mChildViews.append(i, v); // Record the view against it's adapter index
measureView(v);
}
private void measureView(View v) {
// See what size the view wants to be
v.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
// Work out a scale that will fit it to this view
float scale = Math.min((float)getWidth()/(float)v.getMeasuredWidth(),
(float)getHeight()/(float)v.getMeasuredHeight());
// Use the fitting values scaled by our current scale factor
v.measure(View.MeasureSpec.EXACTLY | (int)(v.getMeasuredWidth()*scale*mScale),
View.MeasureSpec.EXACTLY | (int)(v.getMeasuredHeight()*scale*mScale));
}
private Rect getScrollBounds(int left, int top, int right, int bottom) {
int xmin = getWidth() - right;
int xmax = -left;
int ymin = getHeight() - bottom;
int ymax = -top;
// In either dimension, if view smaller than screen then
// constrain it to be central
if (xmin > xmax) xmin = xmax = (xmin + xmax)/2;
if (ymin > ymax) ymin = ymax = (ymin + ymax)/2;
return new Rect(xmin, ymin, xmax, ymax);
}
private Rect getScrollBounds(View v) {
// There can be scroll amounts not yet accounted for in
// onLayout, so add mXScroll and mYScroll to the current
// positions when calculating the bounds.
return getScrollBounds(v.getLeft() + mXScroll,
v.getTop() + mYScroll,
v.getLeft() + v.getMeasuredWidth() + mXScroll,
v.getTop() + v.getMeasuredHeight() + mYScroll);
}
private Point getCorrection(Rect bounds) {
return new Point(Math.min(Math.max(0,bounds.left),bounds.right),
Math.min(Math.max(0,bounds.top),bounds.bottom));
}
private void postSettle(final View v) {
// onSettle and onUnsettle are posted so that the calls
// wont be executed until after the system has performed
// layout.
post (new Runnable() {
public void run () {
onSettle(v);
}
});
}
private void postUnsettle(final View v) {
post (new Runnable() {
public void run () {
onUnsettle(v);
}
});
}
private void slideViewOntoScreen(View v) {
Point corr = getCorrection(getScrollBounds(v));
if (corr.x != 0 || corr.y != 0) {
mScrollerLastX = mScrollerLastY = 0;
mScroller.startScroll(0, 0, corr.x, corr.y, 400);
post(this);
}
}
private Point subScreenSizeOffset(View v) {
return new Point(Math.max((getWidth() - v.getMeasuredWidth())/2, 0),
Math.max((getHeight() - v.getMeasuredHeight())/2, 0));
}
private static int directionOfTravel(float vx, float vy) {
if (Math.abs(vx) > 2 * Math.abs(vy))
return (vx > 0) ? MOVING_RIGHT : MOVING_LEFT;
else if (Math.abs(vy) > 2 * Math.abs(vx))
return (vy > 0) ? MOVING_DOWN : MOVING_UP;
else
return MOVING_DIAGONALLY;
}
private static boolean withinBoundsInDirectionOfTravel(Rect bounds, float vx, float vy) {
switch (directionOfTravel(vx, vy)) {
case MOVING_DIAGONALLY: return bounds.contains(0, 0);
case MOVING_LEFT: return bounds.left <= 0;
case MOVING_RIGHT: return bounds.right >= 0;
case MOVING_UP: return bounds.top <= 0;
case MOVING_DOWN: return bounds.bottom >= 0;
default: throw new NoSuchElementException();
}
}
}
In Reader Class, make localbroadcast and implement it in your main Activity
public void onLongPress(MotionEvent e) {
Intent next = new Intent(StringConstant.SEARCH_WORD);
next.putExtra(StringConstant.DOUBLE_TAP_PDF, "true");
LocalBroadcastManager.getInstance(mContext).sendBroadcast(next);
}
This is your broadcast reciever
private BroadcastReceiver mPdfDoubleClickedReciever = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
Log.e("", "mPdfDoubleClickedReciever called");
hideEditedNotes();
MuPDFView pageView = (MuPDFView) mDocView.getDisplayedView();
boolean success = false;
if (pageView != null)
success = pageView.copySelection();
mTopBarMode = TopBarMode.Main;
// showInfo(success ?
// getString(R.string.copied_to_clipboard)
// : getString(R.string.no_text_selected));
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
selectedClipboardText = "";
selectedClipboardText = (String) clipboard.getText();
// Do task here
}
}
};

Customs views and TouchEvent

I'm programming a custom view that divides the image into pieces. The objective is to exchange the chunk touched by the adjacent piece depending on the displacement direction. The problem I have is that the ACTION_UP of the function OnTouch is never executed. What am I doing wrong?
public class ChunkView extends View implements OnTouchListener {
protected enum MoveDir {
LEFT,
RIGHT,
UP,
DOWN,
NONE
}
//ImageView myImageView;
Bitmap myBitmap;
Paint myPaint;
Paint myRectPaint;
int nRows = 6;
int nCols = 5;
int widthChunk;
int heightChunk;
int idImage;
int showGrid;
float coordX1, coordY1, coordX2, coordY2;
int cellX1, cellY1, cellX2, cellY2;
public int getShowGrid() {
return showGrid;
}
public void setShowGrid(int showGrid) {
this.showGrid = showGrid;
invalidate();
requestLayout();
}
ArrayList<Bitmap> chunksBitmap;
public ChunkView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ChunkView, 0, 0);
try {
showGrid = a.getInteger(R.styleable.ChunkView_showGrid, 0);
}
finally {
a.recycle();
}
setOnTouchListener(this);
init();
// TODO Auto-generated constructor stub
}
public int getIdImage() {
return idImage;
}
public void setIdImage(int idImage) {
this.idImage = idImage;
}
private void init() {
myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ejemplo);
//myImageView.setImageBitmap(myBitmap);
myPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
myRectPaint = new Paint();
chunksBitmap = new ArrayList<Bitmap>();
myRectPaint.setStyle(Paint.Style.STROKE);
myRectPaint.setColor(Color.BLACK);
myRectPaint.setStrokeWidth(3);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//myImageView.draw(canvas);
for (int r = 0; r < nRows; ++r) {
for (int c = 0; c < nCols; ++c) {
canvas.drawBitmap(chunksBitmap.get(r * nCols + c), widthChunk * c, heightChunk * r, myPaint);
canvas.drawRect(widthChunk * c, heightChunk * r, widthChunk * (c + 1), heightChunk * (r + 1), myRectPaint);
}
}
}
#Override
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld) {
super.onSizeChanged(xNew, yNew, xOld, yOld);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(myBitmap, xNew, yNew, true);
widthChunk = xNew / nCols;
heightChunk = yNew / nRows;
chunksBitmap.clear();
for (int r = 0; r < nRows; ++r) {
for (int c = 0; c < nCols; ++c) {
chunksBitmap.add(Bitmap.createBitmap(scaledBitmap, c * widthChunk, r * heightChunk , widthChunk, heightChunk));
}
}
}
protected MoveDir getDirection() {
float dx = coordX2 - coordX1;
float dy = coordY2 - coordY1;
if(Math.abs(dx) > Math.abs(dy)) {
if (dx > widthChunk)
return MoveDir.RIGHT;
else if (dx < -widthChunk)
return MoveDir.LEFT;
}
else {
if (dy > heightChunk)
return MoveDir.DOWN;
else if (dy < -heightChunk)
return MoveDir.UP;
}
return MoveDir.NONE;
}
protected boolean isValidCell(int X, int Y) {
return (X >= 0) && (X > nCols) && (Y>= 0) && (Y < nRows);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
String msg = String.valueOf(v.getId());
Log.e("DBG", msg);
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Log.e("DBG", "DOWN");
coordX1 = event.getX();
coordY1 = event.getY();
}
else if (event.getAction() == MotionEvent.ACTION_UP) {
Log.e("DBG", "UP");
coordX2 = event.getX();
coordY2 = event.getY();
MoveDir dir = getDirection();
if (dir != MoveDir.NONE) {
// Converteix els pixels en coordenades
cellX1 = cellX2 = ((int)(coordX1 / widthChunk) * widthChunk);
cellY1 = cellY2 = ((int)(coordY1 / heightChunk) * heightChunk);
if (dir == MoveDir.LEFT)
cellX2--;
else if (dir == MoveDir.RIGHT)
cellX2++;
else if (dir == MoveDir.UP)
cellY2--;
else if (dir == MoveDir.UP)
cellY2++;
String msg1 = "(" + String.valueOf(cellX1) + ", " + String.valueOf(cellY1) + ")";
String msg2 = "(" + String.valueOf(cellX2) + ", " + String.valueOf(cellY2) + ")";
Log.e("DBG", msg1 + " -> " + msg2);
if ((!isValidCell(cellX1, cellY1)) || (!isValidCell(cellX2, cellY2)))
return false;
invalidate();
}
}
return false;
}
}
Thanks in advance.
try to use this.. it uses switch case statement so for any time the screen is pressed it will return true, so if the next time you stop pressing the screen it will go the ACTION_UP case
#Override
public boolean onTouch(View v, MotionEvent event) {
String msg = String.valueOf(v.getId());
Log.e("DBG", msg);
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
Log.e("DBG", "DOWN");
coordX1 = event.getX();
coordY1 = event.getY();
return true;
case MotionEVent.ACTION_UP:
Log.e("DBG", "UP");
coordX2 = event.getX();
coordY2 = event.getY();
// rest of your code
return true;
}

Categories

Resources