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;
}
Related
I have created a custom view like a crop view which is used in my app to define the cropping area. But the app crashes while inflating the view. May be I have not understood how to use the setColor correctly. I have tried using: BoxPaint.setColor(AppShared.gResources.getColor(R.color.bwff_60)), the app still crashed. Please tell me what all changes I should make in the code so that I'll be able to see the view.
Logcat:
main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/com.md.areadectest"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<FrameLayout
android:id="#+id/layoutMain" android:layout_width="wrap_content" android:layout_height="wrap_content">
<RelativeLayout android:layout_width="#dimen/width_320" android:layout_height="#dimen/width_240" android:layout_centerInParent="true">
<SurfaceView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/preview">
</SurfaceView>
<FrameLayout android:layout_gravity="center" android:id="#+id/layoutDetectArea" android:background="#color/blue" android:layout_width="match_parent" android:layout_height="match_parent">
<com.md.areadectest.AreaDetectorView android:id="#+id/viewDetector" android:layout_width="match_parent" android:layout_height="match_parent" />
</FrameLayout>
</RelativeLayout>
</FrameLayout>
<LinearLayout
android:layout_below="#id/layoutMain"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center">
</LinearLayout>
<ImageView android:id="#+id/myImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_android_black_24dp"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/trigcount"
android:layout_alignTop="#+id/myImageView"
android:layout_centerHorizontal="true"
android:textColor="#android:color/white" />
</RelativeLayout>
View.java
public class AreaDetectorView extends LinearLayout {
public static int Width;
public static int Height;
private static Paint BoxPaint = null;
private static Paint BoxPaint2 = null;
private static Paint TextPaint = null;
private static Paint ArrowPaint = null;
private static Path mPath = null;
private static Rect mRect = null;
private static int lastX, lastY = 0;
private static boolean mBoxTouched = false;
private static boolean mArrowTouched = false;
private static Context mContext;
private static int ArrowWidth = 0;
public AreaDetectorView(Context context) {
super(context);
}
//attrs was not there
public AreaDetectorView(Context context, AttributeSet attrs) {
super(context,attrs);
// TODO Auto-generated constructor stub
if (!this.getRootView().isInEditMode()) {
ArrowWidth =GetDisplayPixel(context, 30);
}
//InitDetectionArea();
InitMemberVariables();
setWillNotDraw(false);
}
public static int GetDisplayPixel(Context paramContext, int paramInt)
{
return (int)(paramInt * paramContext.getResources().getDisplayMetrics().density + 0.5F);
}
public static void InitMemberVariables() {
if (BoxPaint == null) {
BoxPaint = new Paint();
BoxPaint.setAntiAlias(true);
BoxPaint.setStrokeWidth(2.0f);
//BoxPaint.setStyle(Style.STROKE);
BoxPaint.setStyle(Style.FILL_AND_STROKE);
BoxPaint.setColor(ContextCompat.getColor(mContext, R.color.bwff_60));
}
if (ArrowPaint == null) {
ArrowPaint = new Paint();
ArrowPaint.setAntiAlias(true);
ArrowPaint.setColor(ContextCompat.getColor(mContext,R.color.redDD));
ArrowPaint.setStyle(Style.FILL_AND_STROKE);
}
if (TextPaint == null) {
TextPaint = new Paint();
TextPaint.setColor(ContextCompat.getColor(mContext,R.color.yellowL));
TextPaint.setTextSize(16);
//txtPaint.setTypeface(lcd);
TextPaint.setStyle(Style.FILL_AND_STROKE);
}
if (mPath == null) {
mPath = new Path();
} else {
mPath.reset();
}
if (mRect == null) {
mRect = new Rect();
}
if (BoxPaint2 == null) {
BoxPaint2 = new Paint();
BoxPaint2.setAntiAlias(true);
BoxPaint2.setStrokeWidth(2.0f);
//BoxPaint.setStyle(Style.STROKE);
BoxPaint2.setStyle(Style.STROKE);
BoxPaint2.setColor(ContextCompat.getColor(mContext,R.color.bwff_9e));
}
}
public static void InitDetectionArea() {
try {
int w = Preferences.DetectionArea.width();
int h = Preferences.DetectionArea.height();
int x = Preferences.DetectionArea.left;
int y = Preferences.DetectionArea.top;
// ver 2.6.0
if (Preferences.DetectionArea.left == 1
&& Preferences.DetectionArea.top == 1
&& Preferences.DetectionArea.right == 1
&& Preferences.DetectionArea.bottom == 1) {
w = Preferences.DisplayWidth / 4;
h = Preferences.DisplayHeight / 3;
// ver 2.5.9
w = Width / 4;
h = Height / 3;
Preferences.DetectorWidth = w;
Preferences.DetectorHeight = h;
x = (Preferences.DisplayWidth / 2) - (w / 2);
y = (Preferences.DisplayHeight / 2) - (h / 2);
// ver 2.5.9
x = (Width / 2) - (w / 2);
y = (Height / 2) - (h / 2);
}
//Preferences.DetectionArea = new Rect(x, x, x + Preferences.DetectorWidth, x + Preferences.DetectorHeight);
Preferences.DetectionArea = new Rect(x, y, x + w, y + h);
Preferences.gDetectionBitmapInt = new int[Preferences.DetectionArea.width() * Preferences.DetectionArea.height()];
Preferences.gDetectionBitmapIntPrev = new int[Preferences.DetectionArea.width() * Preferences.DetectionArea.height()];
} catch (Exception e) {
e.printStackTrace();
}
}
public static void SetDetectionArea(int x, int y, int w, int h) {
try {
Preferences.DetectionArea = new Rect(x, y, w, h);
} catch (Exception e) {
e.printStackTrace();
}
}
private void DrawAreaBox(Canvas canvas) {
try {
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void dispatchDraw(Canvas canvas) {
try {
if (this.getRootView().isInEditMode()) {
super.dispatchDraw(canvas);
return;
}
//Preferences.DetectionAreaOrient = UtilGeneralHelper.GetDetectRectByOrientation();
canvas.drawColor(0);
mPath.reset();
canvas.drawRect(Preferences.DetectionArea, BoxPaint);
mPath.moveTo(Preferences.DetectionArea.right - ArrowWidth, Preferences.DetectionArea.bottom);
mPath.lineTo(Preferences.DetectionArea.right, Preferences.DetectionArea.bottom - ArrowWidth);
mPath.lineTo(Preferences.DetectionArea.right, Preferences.DetectionArea.bottom);
mPath.lineTo(Preferences.DetectionArea.right - ArrowWidth, Preferences.DetectionArea.bottom);
mPath.close();
canvas.drawPath(mPath, ArrowPaint);
mPath.reset();
//canvas.drawRect(Preferences.DetectionAreaOrient, BoxPaint2);
//canvas.drawRect(Preferences.DetectionAreaOrientPort, BoxPaint2);
TextPaint.setTextSize(16);
TextPaint.setColor(ContextCompat.getColor(mContext,R.color.bwff));
TextPaint.getTextBounds(getResources().getString(R.string.str_detectarea), 0, 1, mRect);
canvas.drawText(getResources().getString(R.string.str_detectarea),
Preferences.DetectionArea.left + 4,
Preferences.DetectionArea.top + 4 + mRect.height(),
TextPaint);
int recH = mRect.height();
TextPaint.setStrokeWidth(1.2f);
TextPaint.setTextSize(18);
TextPaint.setColor(ContextCompat.getColor(mContext,R.color.redD_9e));
TextPaint.getTextBounds(getResources().getString(R.string.str_dragandmove), 0, 1, mRect);
canvas.drawText(getResources().getString(R.string.str_dragandmove),
Preferences.DetectionArea.left + 4,
Preferences.DetectionArea.top + 20 + mRect.height()*2,
TextPaint);
TextPaint.getTextBounds(getResources().getString(R.string.str_scalearea), 0, 1, mRect);
canvas.drawText(getResources().getString(R.string.str_scalearea),
Preferences.DetectionArea.left + 4,
Preferences.DetectionArea.top + 36 + mRect.height()*3,
TextPaint);
super.dispatchDraw(canvas);
//canvas.restore();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void onDraw(Canvas canvas) {
try {
super.onDraw(canvas);
invalidate();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
boolean retValue = true;
int X = (int)event.getX();
int Y = (int)event.getY();
//AppMain.txtLoc.setText(String.valueOf(X) + ", " + String.valueOf(Y));
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mBoxTouched = TouchedInBoxArea(X, Y);
//AppMain.txtLoc.setText("BoxTouched: " + String.valueOf(mBoxTouched));
if (!mBoxTouched) break;
lastX = X;
lastY = Y;
BoxPaint.setStyle(Style.FILL_AND_STROKE);
BoxPaint.setColor(ContextCompat.getColor(mContext,R.color.redD_9e));
mArrowTouched = TouchedInArrow(X, Y);
//AppMain.txtLoc.setText("ArrowTouched: " + String.valueOf(mBoxTouched));
if (mArrowTouched) {
ArrowPaint.setColor(ContextCompat.getColor(mContext,R.color.bwff_9e));
}
break;
case MotionEvent.ACTION_MOVE:
if (!mBoxTouched) break;
int moveX = X - lastX;
int moveY = Y - lastY;
//AppMain.txtLoc.setText("Move X, Y: " + String.valueOf(moveX) + "," + String.valueOf(moveY));
if (!mArrowTouched) {
if (Preferences.DetectionArea.left + moveX < 0) {
break;
}
// if (Preferences.DetectionArea.right + moveX > Preferences.gDisplay.getWidth()) {
// break;
// }
// ver 2.5.9
if (Preferences.DetectionArea.right + moveX > Width) {
break;
}
if (Preferences.DetectionArea.top + moveY < 0) {
break;
}
// if (Preferences.DetectionArea.bottom + moveY > Preferences.gDisplay.getHeight()) {
// break;
// }
// ver 2.5.9
if (Preferences.DetectionArea.bottom + moveY > Height) {
break;
}
}
if (mArrowTouched) {
if ((Preferences.DetectionArea.width() + moveX) < ArrowWidth * 2){
break;
}
if ((Preferences.DetectionArea.height() + moveY) < ArrowWidth * 2) {
break;
}
Preferences.DetectionArea.right += moveX;
Preferences.DetectionArea.bottom += moveY;
//Log.i("DBG", "W,H: " + String.valueOf(Preferences.DetectionArea.width()) + "," + String.valueOf(Preferences.DetectionArea.height()));
} else {
Preferences.DetectionArea.left += moveX;
Preferences.DetectionArea.right += moveX;
Preferences.DetectionArea.top += moveY;
Preferences.DetectionArea.bottom += moveY;
}
lastX = X;
lastY = Y;
//AppMain.txtLoc.setText(String.valueOf(Preferences.DetectionArea.left) + ", " + String.valueOf(Preferences.DetectionArea.top));
break;
case MotionEvent.ACTION_UP:
mBoxTouched = false;
mArrowTouched = false;
//BoxPaint.setStyle(Style.STROKE);
BoxPaint.setStyle(Style.FILL_AND_STROKE);
BoxPaint.setColor(ContextCompat.getColor(mContext,R.color.bwff_60));
ArrowPaint.setColor(ContextCompat.getColor(mContext,R.color.redDD));
//AppMain.txtLoc.setText(String.valueOf(Preferences.DetectionArea.left) + ", " + String.valueOf(Preferences.DetectionArea.top));
if (Preferences.DetectionArea.left < 0) {
Preferences.DetectionArea.left = 0;
}
// if (Preferences.DetectionArea.right > Preferences.gDisplay.getWidth()) {
// Preferences.DetectionArea.right = Preferences.gDisplay.getWidth();
// }
// ver 2.5.9
if (Preferences.DetectionArea.right > Width) {
Preferences.DetectionArea.right = Width;
}
if (Preferences.DetectionArea.top < 0) {
Preferences.DetectionArea.top = 0;
}
// if (Preferences.DetectionArea.bottom > Preferences.gDisplay.getHeight()) {
// Preferences.DetectionArea.bottom = Preferences.gDisplay.getHeight();
// }
if (Preferences.DetectionArea.bottom > Height) {
Preferences.DetectionArea.bottom = Height;
}
Preferences.gDetectionBitmapInt = new int[Preferences.DetectionArea.width() * Preferences.DetectionArea.height()];
Preferences.gDetectionBitmapIntPrev = new int[Preferences.DetectionArea.width() * Preferences.DetectionArea.height()];
//Preferences.gDetectionBitmapInt = null;
//Preferences.gDetectionBitmapIntPrev = null;
String area = String.valueOf(Preferences.DetectionArea.left)
+ "," + String.valueOf(Preferences.DetectionArea.top)
+ "," + String.valueOf(Preferences.DetectionArea.right)
+ "," + String.valueOf(Preferences.DetectionArea.bottom);
// UtilGeneralHelper.SavePreferenceSetting(Preferences.gContext, Preferences.PREF_DETECTION_AREA_KEY, area);
break;
}
invalidate();
return retValue;
}
private boolean TouchedInBoxArea(int x, int y) {
boolean retValue = false;
try {
if (x > Preferences.DetectionArea.left && x < Preferences.DetectionArea.right) {
if (y > Preferences.DetectionArea.top && y < Preferences.DetectionArea.bottom) {
retValue = true;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return retValue;
}
private boolean TouchedInArrow(int x, int y) {
boolean retValue = false;
try {
if (x > Preferences.DetectionArea.right - ArrowWidth && x < Preferences.DetectionArea.right) {
if (y > Preferences.DetectionArea.bottom - ArrowWidth && y < Preferences.DetectionArea.bottom) {
retValue = true;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return retValue;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
Width = width;
Height = height;
InitDetectionArea();
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
for (int i = 0; i < this.getChildCount()-1; i++){
(this.getChildAt(i)).layout(l, t, r, b);
}
if (changed) {
// check width height
if (r != Width || b != Height) {
// size does not match
}
}
}
}
The problem is that your variable mContextis null - you need to set mContext = context in your constructors.
Try this:
BoxPaint.setColor(getResources().getColor(R.color.bwff_60));
color only apply when you added in
your-project\app\src\main\res\values\colors.xml file.
Hi i have created custom view "Number Bar" which is working fine. I just want to add labels on each indicator. I tried that but when i draw text it is not visible because view is not getting height for that. Please check image below thanks.
View onDraw Source Code
protected void onDraw(Canvas canvas) {
int indicatorWidthHeight = Utils.dpToPx(getContext(), indicatorSize);
indicatorRadius = indicatorWidthHeight / 2;
int cx = indicatorWidthHeight / 2;
int cy = indicatorWidthHeight / 2;
int totalIndicators = 5;
int totalLines = totalIndicators - 1;
int lineWidth = (getMeasuredWidth() - (indicatorWidthHeight * totalIndicators)) / totalLines;
linePaint.setStrokeWidth(Utils.dpToPx(getContext(), lineHeight));
for (int i = 0; i < circles.length; i++) {
if (selected >= i) {
indicatorPaint.setColor(selectedBackgroundColor);
textPaint.setColor(selectedTextColor);
} else {
indicatorPaint.setColor(backgroundColor);
textPaint.setColor(textColor);
}
if (selected >= i + 1) {
linePaint.setColor(selectedBackgroundColor);
} else {
linePaint.setColor(backgroundColor);
}
int nCx = cx + (lineWidth + indicatorRadius * 2) * i;
circles[i].setRadius(indicatorRadius);
circles[i].setX(nCx);
circles[i].setY(cy);
canvas.drawCircle(nCx, cy, indicatorRadius, indicatorPaint);
String text = "" + (i+1);
textPaint.getTextBounds(text, 0, text.length(), rect);
canvas.drawText(text, nCx, cy+rect.height()/2, textPaint);
// Draw lines one less than circles
if (i != circles.length - 1) {
int startX = nCx + indicatorRadius;
int stopX = nCx + indicatorRadius + lineWidth;
lines[i].setStartX(startX);
lines[i].setStartY(cy);
lines[i].setStopX(stopX);
lines[i].setStopY(cy);
canvas.drawLine(startX, cy, stopX, cy, linePaint);
}
}
}
View Full Source Code
public class NumberBar extends View {
public static final int DEFAULT_TEXT_SIZE = 16;
public static final int DEF_INDICATOR_SIZE = 20;
Rect rect = new Rect();
Circle[] circles = new Circle[5];
Line[] lines = new Line[4];
private int backgroundColor, textColor, selectedBackgroundColor, selectedTextColor, indicatorSize, lineHeight, selected;
private Paint indicatorPaint;
private Paint textPaint;
private Paint linePaint;
private int indicatorRadius;
private boolean enabled = true;
public NumberBar(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.NumberBar, 0, 0);
try {
backgroundColor = typedArray.getInteger(R.styleable.NumberBar_backgroundColor, Color.parseColor("#eeeeee"));
selectedBackgroundColor = typedArray.getInteger(R.styleable.NumberBar_selectedBackgroundColor, Color.parseColor("#0171fe"));
textColor = typedArray.getInteger(R.styleable.NumberBar_textColor, Color.parseColor("#c8c8c8"));
selectedTextColor = typedArray.getInteger(R.styleable.NumberBar_selectedTextColor, Color.parseColor("#ffffff"));
indicatorSize = typedArray.getInteger(R.styleable.NumberBar_indicatorSize, DEF_INDICATOR_SIZE);
lineHeight = typedArray.getInteger(R.styleable.NumberBar_lineHeight, 3);
selected = typedArray.getInteger(R.styleable.NumberBar_selected, 0);
enabled = typedArray.getBoolean(R.styleable.NumberBar_enabled, true);
} finally {
typedArray.recycle();
}
for (int i = 0; i < circles.length; i++) {
circles[i] = new Circle();
}
for (int i = 0; i < lines.length; i++) {
lines[i] = new Line();
}
indicatorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
indicatorPaint.setStyle(Paint.Style.FILL);
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setTextAlign(Paint.Align.CENTER);
textPaint.setTextSize(Utils.spToPx(getContext(), DEFAULT_TEXT_SIZE));
linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
linePaint.setStyle(Paint.Style.FILL_AND_STROKE);
}
#Override
protected void onDraw(Canvas canvas) {
int indicatorWidthHeight = Utils.dpToPx(getContext(), indicatorSize);
indicatorRadius = indicatorWidthHeight / 2;
int cx = indicatorWidthHeight / 2;
int cy = indicatorWidthHeight / 2;
int totalIndicators = 5;
int totalLines = totalIndicators - 1;
int lineWidth = (getMeasuredWidth() - (indicatorWidthHeight * totalIndicators)) / totalLines;
linePaint.setStrokeWidth(Utils.dpToPx(getContext(), lineHeight));
for (int i = 0; i < circles.length; i++) {
if (selected >= i) {
indicatorPaint.setColor(selectedBackgroundColor);
textPaint.setColor(selectedTextColor);
} else {
indicatorPaint.setColor(backgroundColor);
textPaint.setColor(textColor);
}
if (selected >= i + 1) {
linePaint.setColor(selectedBackgroundColor);
} else {
linePaint.setColor(backgroundColor);
}
int nCx = cx + (lineWidth + indicatorRadius * 2) * i;
circles[i].setRadius(indicatorRadius);
circles[i].setX(nCx);
circles[i].setY(cy);
canvas.drawCircle(nCx, cy, indicatorRadius, indicatorPaint);
String text = "" + (i+1);
textPaint.getTextBounds(text, 0, text.length(), rect);
canvas.drawText(text, nCx, cy+rect.height()/2, textPaint);
// Draw lines one less than circles
if (i != circles.length - 1) {
int startX = nCx + indicatorRadius;
int stopX = nCx + indicatorRadius + lineWidth;
lines[i].setStartX(startX);
lines[i].setStartY(cy);
lines[i].setStopX(stopX);
lines[i].setStopY(cy);
canvas.drawLine(startX, cy, stopX, cy, linePaint);
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!enabled) {
return true;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
handleDownTouch(event.getX(), event.getY());
break;
}
return true;
}
private void handleDownTouch(float eventX, float eventY) {
for (int i = 0; i < circles.length; i++) {
if (isCircleClicked(eventX, eventY, circles[i])) { // Toast.makeText(NumberBar.this.getContext(), "Circle Clicked: " + i, Toast.LENGTH_SHORT).show();
this.selected = i;
invalidate();
return;
}
}
for (int i = 0; i < lines.length; i++) {
if (inLine(lines[i].getStartPoint(), lines[i].getStopPoint(), new Point((int)eventX, (int)eventY))) {
this.selected = i+1;
invalidate();
return; // Toast.makeText(NumberBar.this.getContext(), "Line: " + i, Toast.LENGTH_SHORT).show();
}
}
}
// is BC inline with AC or visa-versa
public boolean inLine(Point A, Point B, Point C) {
int offset = 5;
return C.x >= A.x && C.x <= B.x && (C.y <= (B.y-lineHeight+ offset) || C.y <= (B.y-lineHeight- offset));
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // Don't measure width its most or which user will give
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int height;
//Measure Height
if (heightMode == MeasureSpec.EXACTLY) {
//Must be this size
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
height = Math.min(indicatorSize, heightSize);
} else {
//Be whatever you want
height = indicatorSize;
}
//MUST CALL THIS
setMeasuredDimension(widthSize, height);
setMeasuredDimension(getMeasuredWidth(), Utils.dpToPx(getContext(), indicatorSize));
}
private boolean isCircleClicked(float ex, float ey, Circle circle) {
return Math.sqrt((circle.getX() - ex) * (circle.getX() - ex) + (circle.getY() - ey) * (circle.getY() - ey)) < circle.getRadius()+4;
}
public int getBackgroundColor() {
return backgroundColor;
}
#Override
public void setBackgroundColor(int backgroundColor) {
this.backgroundColor = backgroundColor;
invalidate();
}
public int getTextColor() {
return textColor;
}
public void setTextColor(int textColor) {
this.textColor = textColor;
invalidate();
}
public int getSelectedBackgroundColor() {
return selectedBackgroundColor;
}
public void setSelectedBackgroundColor(int selectedBackgroundColor) {
this.selectedBackgroundColor = selectedBackgroundColor;
invalidate();
}
public int getSelectedTextColor() {
return selectedTextColor;
}
public void setSelectedTextColor(int selectedTextColor) {
this.selectedTextColor = selectedTextColor;
invalidate();
}
public int getIndicatorSize() {
return indicatorSize;
}
public void setIndicatorSize(int indicatorSize) {
this.indicatorSize = indicatorSize;
invalidate();
requestLayout();
}
public int getLineHeight() {
return lineHeight;
}
public void setLineHeight(int lineHeight) {
this.lineHeight = lineHeight;
invalidate();
requestLayout();
}
public int getSelected() {
return selected;
}
public void setSelected(int selected) {
this.selected = selected;
invalidate();
}
private class Circle {
int x, y;
int radius;
public Circle() {
}
public Circle(int x, int y, int radius) {
this.x = x;
this.y = y;
this.radius = radius;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
}
class Line {
Point startPoint = new Point();
Point stopPoint = new Point();
public int getStartX() {
return startPoint.x;
}
public void setStartX(int startX) {
this.startPoint.x = startX;
}
public int getStartY() {
return startPoint.y;
}
public void setStartY(int startY) {
this.startPoint.y = startY;
}
public int getStopX() {
return stopPoint.x;
}
public void setStopX(int stopX) {
this.stopPoint.x = stopX;
}
public int getStopY() {
return stopPoint.y;
}
public void setStopY(int stopY) {
this.stopPoint.y = stopY;
}
public Point getStartPoint() {
return startPoint;
}
public Point getStopPoint() {
return stopPoint;
}
}
#Override
public boolean isEnabled() {
return enabled;
}
#Override
public void setEnabled(boolean enabled) {
this.enabled = enabled;
} }
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.
I want make fold animation in both horizontal & vertical and i followed the below link for (DevBytes) for making folding animation.However this works for only for single image. How to make it to work for multiple Image Folding one by one (By swiping and autoplay)
Folding Layout class:
public class FoldingLayout extends ViewGroup {
public static enum Orientation {
VERTICAL,
HORIZONTAL
}
private final String FOLDING_VIEW_EXCEPTION_MESSAGE = "Folding Layout can only 1 child at " +
"most";
private final float SHADING_ALPHA = 0.8f;
private final float SHADING_FACTOR = 0.5f;
private final int DEPTH_CONSTANT = 1500;
private final int NUM_OF_POLY_POINTS = 8;
private Rect[] mFoldRectArray;
private Matrix [] mMatrix;
private Orientation mOrientation = Orientation.HORIZONTAL;
private float mAnchorFactor = 0;
private float mFoldFactor = 0;
private int mNumberOfFolds = 2;
private boolean mIsHorizontal = true;
private int mOriginalWidth = 0;
private int mOriginalHeight = 0;
private float mFoldMaxWidth = 0;
private float mFoldMaxHeight = 0;
private float mFoldDrawWidth = 0;
private float mFoldDrawHeight = 0;
private boolean mIsFoldPrepared = false;
private boolean mShouldDraw = true;
private Paint mSolidShadow;
private Paint mGradientShadow;
private LinearGradient mShadowLinearGradient;
private Matrix mShadowGradientMatrix;
private float [] mSrc;
private float [] mDst;
private OnFoldListener mFoldListener;
private float mPreviousFoldFactor = 0;
private Bitmap mFullBitmap;
private Rect mDstRect;
public FoldingLayout(Context context) {
super(context);
}
public FoldingLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FoldingLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected boolean addViewInLayout(View child, int index, LayoutParams params,
boolean preventRequestLayout) {
throwCustomException(getChildCount());
boolean returnValue = super.addViewInLayout(child, index, params, preventRequestLayout);
return returnValue;
}
#Override
public void addView(View child, int index, LayoutParams params) {
throwCustomException(getChildCount());
super.addView(child, index, params);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
View child = getChildAt(0);
measureChild(child,widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
View child = getChildAt(0);
child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
updateFold();
}
private class NumberOfFoldingLayoutChildrenException extends RuntimeException {
public NumberOfFoldingLayoutChildrenException(String message) {
super(message);
}
}
private void throwCustomException (int numOfChildViews) {
if (numOfChildViews == 1) {
throw new NumberOfFoldingLayoutChildrenException(FOLDING_VIEW_EXCEPTION_MESSAGE);
}
}
public void setFoldListener(OnFoldListener foldListener) {
mFoldListener = foldListener;
}
public void setFoldFactor(float foldFactor) {
if (foldFactor != mFoldFactor) {
mFoldFactor = foldFactor;
calculateMatrices();
invalidate();
}
}
public void setOrientation(Orientation orientation) {
if (orientation != mOrientation) {
mOrientation = orientation;
updateFold();
}
}
public void setAnchorFactor(float anchorFactor) {
if (anchorFactor != mAnchorFactor) {
mAnchorFactor = anchorFactor;
updateFold();
}
}
public void setNumberOfFolds(int numberOfFolds) {
if (numberOfFolds != mNumberOfFolds) {
mNumberOfFolds = numberOfFolds;
updateFold();
}
}
public float getAnchorFactor() {
return mAnchorFactor;
}
public Orientation getOrientation() {
return mOrientation;
}
public float getFoldFactor() {
return mFoldFactor;
}
public int getNumberOfFolds() {
return mNumberOfFolds;
}
private void updateFold() {
prepareFold(mOrientation, mAnchorFactor, mNumberOfFolds);
calculateMatrices();
invalidate();
}
private void prepareFold(Orientation orientation, float anchorFactor, int numberOfFolds) {
mSrc = new float[NUM_OF_POLY_POINTS];
mDst = new float[NUM_OF_POLY_POINTS];
mDstRect = new Rect();
mFoldFactor = 0;
mPreviousFoldFactor = 0;
mIsFoldPrepared = false;
mSolidShadow = new Paint();
mGradientShadow = new Paint();
mOrientation = orientation;
mIsHorizontal = (orientation == Orientation.HORIZONTAL);
if (mIsHorizontal) {
mShadowLinearGradient = new LinearGradient(0, 0, SHADING_FACTOR, 0, Color.BLACK,
Color.TRANSPARENT, TileMode.CLAMP);
} else {
mShadowLinearGradient = new LinearGradient(0, 0, 0, SHADING_FACTOR, Color.BLACK,
Color.TRANSPARENT, TileMode.CLAMP);
}
mGradientShadow.setStyle(Style.FILL);
mGradientShadow.setShader(mShadowLinearGradient);
mShadowGradientMatrix = new Matrix();
mAnchorFactor = anchorFactor;
mNumberOfFolds = numberOfFolds;
mOriginalWidth = getMeasuredWidth();
mOriginalHeight = getMeasuredHeight();
mFoldRectArray = new Rect[mNumberOfFolds];
mMatrix = new Matrix [mNumberOfFolds];
for (int x = 0; x < mNumberOfFolds; x++) {
mMatrix[x] = new Matrix();
}
int h = mOriginalHeight;
int w = mOriginalWidth;
if (FoldingLayoutActivity.IS_JBMR2) {
mFullBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(mFullBitmap);
getChildAt(0).draw(canvas);
}
int delta = Math.round(mIsHorizontal ? ((float) w) / ((float) mNumberOfFolds) :
((float) h) /((float) mNumberOfFolds));
for (int x = 0; x < mNumberOfFolds; x++) {
if (mIsHorizontal) {
int deltap = (x + 1) * delta > w ? w - x * delta : delta;
mFoldRectArray[x] = new Rect(x * delta, 0, x * delta + deltap, h);
} else {
int deltap = (x + 1) * delta > h ? h - x * delta : delta;
mFoldRectArray[x] = new Rect(0, x * delta, w, x * delta + deltap);
}
}
if (mIsHorizontal) {
mFoldMaxHeight = h;
mFoldMaxWidth = delta;
} else {
mFoldMaxHeight = delta;
mFoldMaxWidth = w;
}
mIsFoldPrepared = true;
}
private void calculateMatrices() {
mShouldDraw = true;
if (!mIsFoldPrepared) {
return;
}
if (mFoldFactor == 1) {
mShouldDraw = false;
return;
}
if (mFoldFactor == 0 && mPreviousFoldFactor > 0) {
mFoldListener.onEndFold();
}
if (mPreviousFoldFactor == 0 && mFoldFactor > 0) {
mFoldListener.onStartFold();
}
mPreviousFoldFactor = mFoldFactor;
for (int x = 0; x < mNumberOfFolds; x++) {
mMatrix[x].reset();
}
float cTranslationFactor = 1 - mFoldFactor;
float translatedDistance = mIsHorizontal ? mOriginalWidth * cTranslationFactor :
mOriginalHeight * cTranslationFactor;
float translatedDistancePerFold = Math.round(translatedDistance / mNumberOfFolds);
mFoldDrawWidth = mFoldMaxWidth < translatedDistancePerFold ?
translatedDistancePerFold : mFoldMaxWidth;
mFoldDrawHeight = mFoldMaxHeight < translatedDistancePerFold ?
translatedDistancePerFold : mFoldMaxHeight;
float translatedDistanceFoldSquared = translatedDistancePerFold * translatedDistancePerFold;
float depth = mIsHorizontal ?
(float)Math.sqrt((double)(mFoldDrawWidth * mFoldDrawWidth -
translatedDistanceFoldSquared)) :
(float)Math.sqrt((double)(mFoldDrawHeight * mFoldDrawHeight -
translatedDistanceFoldSquared));
float scaleFactor = DEPTH_CONSTANT / (DEPTH_CONSTANT + depth);
float scaledWidth, scaledHeight, bottomScaledPoint, topScaledPoint, rightScaledPoint,
leftScaledPoint;
if (mIsHorizontal) {
scaledWidth = mFoldDrawWidth * cTranslationFactor;
scaledHeight = mFoldDrawHeight * scaleFactor;
} else {
scaledWidth = mFoldDrawWidth * scaleFactor;
scaledHeight = mFoldDrawHeight * cTranslationFactor;
}
topScaledPoint = (mFoldDrawHeight - scaledHeight) / 2.0f;
bottomScaledPoint = topScaledPoint + scaledHeight;
leftScaledPoint = (mFoldDrawWidth - scaledWidth) / 2.0f;
rightScaledPoint = leftScaledPoint + scaledWidth;
float anchorPoint = mIsHorizontal ? mAnchorFactor * mOriginalWidth :
mAnchorFactor * mOriginalHeight;
/* The fold along which the anchor point is located. */
float midFold = mIsHorizontal ? (anchorPoint / mFoldDrawWidth) : anchorPoint /
mFoldDrawHeight;
mSrc[0] = 0;
mSrc[1] = 0;
mSrc[2] = 0;
mSrc[3] = mFoldDrawHeight;
mSrc[4] = mFoldDrawWidth;
mSrc[5] = 0;
mSrc[6] = mFoldDrawWidth;
mSrc[7] = mFoldDrawHeight;
for (int x = 0; x < mNumberOfFolds; x++) {
boolean isEven = (x % 2 == 0);
if (mIsHorizontal) {
mDst[0] = (anchorPoint > x * mFoldDrawWidth) ? anchorPoint + (x - midFold) *
scaledWidth : anchorPoint - (midFold - x) * scaledWidth;
mDst[1] = isEven ? 0 : topScaledPoint;
mDst[2] = mDst[0];
mDst[3] = isEven ? mFoldDrawHeight: bottomScaledPoint;
mDst[4] = (anchorPoint > (x + 1) * mFoldDrawWidth) ? anchorPoint + (x + 1 - midFold)
* scaledWidth : anchorPoint - (midFold - x - 1) * scaledWidth;
mDst[5] = isEven ? topScaledPoint : 0;
mDst[6] = mDst[4];
mDst[7] = isEven ? bottomScaledPoint : mFoldDrawHeight;
} else {
mDst[0] = isEven ? 0 : leftScaledPoint;
mDst[1] = (anchorPoint > x * mFoldDrawHeight) ? anchorPoint + (x - midFold) *
scaledHeight : anchorPoint - (midFold - x) * scaledHeight;
mDst[2] = isEven ? leftScaledPoint: 0;
mDst[3] = (anchorPoint > (x + 1) * mFoldDrawHeight) ? anchorPoint + (x + 1 -
midFold) * scaledHeight : anchorPoint - (midFold - x - 1) * scaledHeight;
mDst[4] = isEven ? mFoldDrawWidth : rightScaledPoint;
mDst[5] = mDst[1];
mDst[6] = isEven ? rightScaledPoint : mFoldDrawWidth;
mDst[7] = mDst[3];
}
for (int y = 0; y < 8; y ++) {
mDst[y] = Math.round(mDst[y]);
}
int alpha = (int) (mFoldFactor * 255 * SHADING_ALPHA);
mSolidShadow.setColor(Color.argb(alpha, 0, 0, 0));
if (mIsHorizontal) {
mShadowGradientMatrix.setScale(mFoldDrawWidth, 1);
mShadowLinearGradient.setLocalMatrix(mShadowGradientMatrix);
} else {
mShadowGradientMatrix.setScale(1, mFoldDrawHeight);
mShadowLinearGradient.setLocalMatrix(mShadowGradientMatrix);
}
mGradientShadow.setShader(mShadowLinearGradient);
mGradientShadow.setAlpha(alpha);
}
#Override
protected void dispatchDraw(Canvas canvas) {
if (!mIsFoldPrepared || mFoldFactor == 0) {
super.dispatchDraw(canvas);
return;
}
if (!mShouldDraw) {
return;
}
for (int x = 0; x < mNumberOfFolds; x++) {
src = mFoldRectArray[x];
canvas.concat(mMatrix[x]);
if (FoldingLayoutActivity.IS_JBMR2) {
mDstRect.set(0, 0, src.width(), src.height());
canvas.drawBitmap(mFullBitmap, src, mDstRect, null);
} else {
canvas.clipRect(0, 0, src.right - src.left, src.bottom - src.top);
if (mIsHorizontal) {
canvas.translate(-src.left, 0);
} else {
canvas.translate(0, -src.top);
}
super.dispatchDraw(canvas);
if (mIsHorizontal) {
canvas.translate(src.left, 0);
} else {
canvas.translate(0, src.top);
}
}
if (x % 2 == 0) {
canvas.drawRect(0, 0, mFoldDrawWidth, mFoldDrawHeight, mSolidShadow);
} else {
canvas.drawRect(0, 0, mFoldDrawWidth, mFoldDrawHeight, mGradientShadow);
}
canvas.restore();
}
}
}
// onFoldListener
public interface OnFoldListener {
public void onStartFold();
public void onEndFold();
}
// FoldingLayoutActivity
public class FoldingLayoutActivity extends Activity {
private final int ANTIALIAS_PADDING = 1;
private final int FOLD_ANIMATION_DURATION = 1000;
static final boolean IS_JBMR2 = Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR2;
private FoldingLayout mFoldLayout;
private SeekBar mAnchorSeekBar;
private Orientation mOrientation = Orientation.HORIZONTAL;
private int mTranslation = 0;
private int mNumberOfFolds = 2;
private int mParentPositionY = -1;
private int mTouchSlop = -1;
private float mAnchorFactor = 0;
private boolean mDidLoadSpinner = true;
private boolean mDidNotStartScroll = true;
private boolean mIsCameraFeed = false;
private boolean mIsSepiaOn = true;
private GestureDetector mScrollGestureDetector;
private ItemSelectedListener mItemSelectedListener;
private Camera mCamera;
private TextureView mTextureView;
private ImageView mImageView;
private Paint mSepiaPaint;
private Paint mDefaultPaint;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fold);
mImageView = (ImageView)findViewById(R.id.image_view);
mImageView.setPadding(ANTIALIAS_PADDING, ANTIALIAS_PADDING, ANTIALIAS_PADDING,
ANTIALIAS_PADDING);
mImageView.setScaleType(ImageView.ScaleType.FIT_XY);
mImageView.setImageDrawable(getResources().getDrawable(R.drawable.image));
mTextureView = new TextureView(this);
mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
mAnchorSeekBar = (SeekBar)findViewById(R.id.anchor_seek_bar);
mFoldLayout = (FoldingLayout)findViewById(R.id.fold_view);
mFoldLayout.setBackgroundColor(Color.BLACK);
mFoldLayout.setFoldListener(mOnFoldListener);
mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
mAnchorSeekBar.setOnSeekBarChangeListener(mSeekBarChangeListener);
mScrollGestureDetector = new GestureDetector(this, new ScrollGestureDetector());
mItemSelectedListener = new ItemSelectedListener();
mDefaultPaint = new Paint();
mSepiaPaint = new Paint();
ColorMatrix m1 = new ColorMatrix();
ColorMatrix m2 = new ColorMatrix();
m1.setSaturation(0);
m2.setScale(1f, .95f, .82f, 1.0f);
m1.setConcat(m2, m1);
mSepiaPaint.setColorFilter(new ColorMatrixColorFilter(m1));
}
private OnFoldListener mOnFoldListener =
new OnFoldListener() {
#Override
public void onStartFold() {
if (mIsSepiaOn) {
setSepiaLayer(mFoldLayout.getChildAt(0), true);
}
}
#Override
public void onEndFold() {
setSepiaLayer(mFoldLayout.getChildAt(0), false);
}
};
private void setSepiaLayer (View view, boolean isSepiaLayerOn) {
if (!IS_JBMR2) {
if (isSepiaLayerOn) {
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
view.setLayerPaint(mSepiaPaint);
} else {
view.setLayerPaint(mDefaultPaint);
}
}
}
private TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView
.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i2) {
mCamera = Camera.open();
if (mCamera == null && Camera.getNumberOfCameras() > 1) {
mCamera = mCamera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
}
if (mCamera == null) {
return;
}
try {
mCamera.setPreviewTexture(surfaceTexture);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i2) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
}
return true;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
};
private SeekBar.OnSeekBarChangeListener mSeekBarChangeListener = new SeekBar
.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
mTranslation = 0;
mAnchorFactor = ((float)mAnchorSeekBar.getProgress())/100.0f;
mFoldLayout.setAnchorFactor(mAnchorFactor);
}
};
#Override
public boolean onCreateOptionsMenu(Menu menu) {
if (IS_JBMR2) {
getMenuInflater().inflate(R.menu.fold_with_bug, menu);
} else {
getMenuInflater().inflate(R.menu.fold, menu);
}
Spinner s = (Spinner) menu.findItem(R.id.num_of_folds).getActionView();
s.setOnItemSelectedListener(mItemSelectedListener);
return true;
}
#Override
public void onWindowFocusChanged (boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
int[] loc = new int[2];
mFoldLayout.getLocationOnScreen(loc);
mParentPositionY = loc[1];
}
#Override
public boolean onTouchEvent(MotionEvent me) {
return mScrollGestureDetector.onTouchEvent(me);
}
#Override
public boolean onOptionsItemSelected (MenuItem item) {
switch(item.getItemId()) {
case R.id.animate_fold:
animateFold();
break;
case R.id.toggle_orientation:
mOrientation = (mOrientation == Orientation.HORIZONTAL) ? Orientation.VERTICAL :
Orientation.HORIZONTAL;
item.setTitle((mOrientation == Orientation.HORIZONTAL) ? R.string.vertical :
R.string.horizontal);
mTranslation = 0;
mFoldLayout.setOrientation(mOrientation);
break;
case R.id.camera_feed:
mIsCameraFeed = !mIsCameraFeed;
item.setTitle(mIsCameraFeed ? R.string.static_image : R.string.camera_feed);
item.setChecked(mIsCameraFeed);
if (mIsCameraFeed) {
mFoldLayout.removeView(mImageView);
mFoldLayout.addView(mTextureView, new ViewGroup.LayoutParams(
mFoldLayout.getWidth(), mFoldLayout.getHeight()));
} else {
mFoldLayout.removeView(mTextureView);
mFoldLayout.addView(mImageView, new ViewGroup.LayoutParams(
mFoldLayout.getWidth(), mFoldLayout.getHeight()));
}
mTranslation = 0;
break;
case R.id.sepia:
mIsSepiaOn = !mIsSepiaOn;
item.setChecked(!mIsSepiaOn);
if (mIsSepiaOn && mFoldLayout.getFoldFactor() != 0) {
setSepiaLayer(mFoldLayout.getChildAt(0), true);
} else {
setSepiaLayer(mFoldLayout.getChildAt(0), false);
}
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
public void animateFold ()
{
float foldFactor = mFoldLayout.getFoldFactor();
ObjectAnimator animator = ObjectAnimator.ofFloat(mFoldLayout, "foldFactor", foldFactor, 1);
animator.setRepeatMode(ValueAnimator.REVERSE);
animator.setRepeatCount(1);
animator.setDuration(FOLD_ANIMATION_DURATION);
animator.setInterpolator(new AccelerateInterpolator());
animator.start();
}
private class ItemSelectedListener implements OnItemSelectedListener {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
mNumberOfFolds = Integer.parseInt(parent.getItemAtPosition(pos).toString());
if (mDidLoadSpinner) {
mDidLoadSpinner = false;
} else {
mTranslation = 0;
mFoldLayout.setNumberOfFolds(mNumberOfFolds);
}
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
}
}
private class ScrollGestureDetector extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onDown (MotionEvent e) {
mDidNotStartScroll = true;
return true;
}
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
int touchSlop = 0;
float factor;
if (mOrientation == Orientation.VERTICAL) {
factor = Math.abs((float)(mTranslation) / (float)(mFoldLayout.getHeight()));
if (e2.getY() - mParentPositionY <= mFoldLayout.getHeight()
&& e2.getY() - mParentPositionY >= 0) {
if ((e2.getY() - mParentPositionY) > mFoldLayout.getHeight() * mAnchorFactor) {
mTranslation -= (int)distanceY;
touchSlop = distanceY < 0 ? -mTouchSlop : mTouchSlop;
} else {
mTranslation += (int)distanceY;
touchSlop = distanceY < 0 ? mTouchSlop : -mTouchSlop;
}
mTranslation = mDidNotStartScroll ? mTranslation + touchSlop : mTranslation;
if (mTranslation < -mFoldLayout.getHeight()) {
mTranslation = -mFoldLayout.getHeight();
}
}
} else {
factor = Math.abs(((float)mTranslation) / ((float) mFoldLayout.getWidth()));
if (e2.getRawX() > mFoldLayout.getWidth() * mAnchorFactor) {
mTranslation -= (int)distanceX;
touchSlop = distanceX < 0 ? -mTouchSlop : mTouchSlop;
} else {
mTranslation += (int)distanceX;
touchSlop = distanceX < 0 ? mTouchSlop : -mTouchSlop;
}
mTranslation = mDidNotStartScroll ? mTranslation + touchSlop : mTranslation;
if (mTranslation < -mFoldLayout.getWidth()) {
mTranslation = -mFoldLayout.getWidth();
}
}
mDidNotStartScroll = false;
if (mTranslation > 0) {
mTranslation = 0;
}
mFoldLayout.setFoldFactor(factor);
return true;
}
}
}
//activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.example.android.foldinglayout.FoldingLayout
android:layout_weight="1"
android:id="#+id/fold_view"
android:layout_width="match_parent"
android:layout_height="0dp">
<ImageView
android:id="#+id/image_view"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:scaleType="fitXY"/>
</com.example.android.foldinglayout.FoldingLayout>
<SeekBar
android:id="#+id/anchor_seek_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"/>
</LinearLayout>
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();
}