Related
Rajawali Version or Branch
rajawali:1.0.186
Device and Android Version
ADV Nexus 5X API 19 Android 4.4
Summary
I'm trying to make the camera moves when a MotionEvent (touch) occurs. I tried the code from https://github.com/Rajawali/Rajawali/issues/428 but it did not work for me.
My code
public class Renderer extends RajawaliRenderer {
public Context context;
private DirectionalLight directionalLight;
public Renderer(Context context) {
super(context);
this.context = context;
setFrameRate(60);
}
private Object3D object, star;
public void initScene(){
getCurrentScene().setBackgroundColor(Color.rgb(5,104,255));
directionalLight = new DirectionalLight(1f, .2f, -1.0f);
directionalLight.setColor(1.0f, 1.0f, 1.0f);
directionalLight.setPower(2);
getCurrentScene().addLight(directionalLight);
//LoaderOBJ objParser = new LoaderOBJ(this,"Load/1c_obj");
LoaderOBJ objParser = new LoaderOBJ(mContext.getResources(),mTextureManager, R.raw.primo_obj);
LoaderOBJ starParser = new LoaderOBJ(mContext.getResources(),mTextureManager,R.raw.star_obj);
try {
objParser.parse();
starParser.parse();
object = objParser.getParsedObject();
star = starParser.getParsedObject();
getCurrentScene().addChild(star);
getCurrentScene().addChild(object);
} catch (ParsingException e) {
e.printStackTrace();
}
getCurrentCamera().setLookAt(object.getWorldPosition());
Log.d("->",getCurrentCamera().getX()+","+getCurrentCamera().getY()+","+getCurrentCamera().getZ());
getCurrentCamera().setZ(40);
}
#Override
public void onRender(final long elapsedTime, final double deltaTime) {
super.onRender(elapsedTime, deltaTime);
Camera cam = getCurrentCamera();
Vector3 s = cam.getPosition();
if (touchTurn != 0) {
if (flagMulti) {
Double r = Math.sqrt(s.x * s.x + s.z * s.z);
angle += touchTurn;
angle %= 360;
cam.setPosition((float) (r * Math.cos(angle)), s.y, (float) (r * Math.sin(angle)));
cam.setLookAt(object.getLookAt());
}
else{
s.x+=touchTurn*5;
cam.setPosition(s);
}
touchTurn = 0;
}
if (touchTurnUp != 0) {
if (!flagMulti) {
s.z += touchTurnUp * 5;
cam.setPosition(s);
}
touchTurnUp = 0;
}
}
#Override
public void onTouchEvent(MotionEvent me){
Log.d("touch ","Log touch");
int pointerCount = me.getPointerCount();
if(pointerCount == 2)
flagMulti = true;
if (me.getAction() == MotionEvent.ACTION_DOWN) {
xpos = me.getX();
ypos = me.getY();
}
if (me.getAction() == MotionEvent.ACTION_UP) {
xpos = -1;
ypos = -1;
touchTurn = 0;
touchTurnUp = 0;
}
if (me.getAction() == MotionEvent.ACTION_MOVE) {
float xd = me.getX() - xpos;
float yd = me.getY() - ypos;
xpos = me.getX();
ypos = me.getY();
touchTurn = xd / -100f;
touchTurnUp = yd / -100f;
Log.d("touchTurn ", touchTurn+" - "+touchTurnUp);
}
try {
Thread.sleep(15);
} catch (Exception e) {
}
}
public void onOffsetsChanged(float x, float y, float z, float w, int i, int j){
}}
Would you consider arcballCamera and target to your 3D object. You can then rotate the 3D object and zoom in/out with arcballCamera.
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>
Here is my source code.
/*
* This code is a modification of the Android LunarLander example.
*/
package net.simplifiedcoding.detectoutgoingcalls.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.media.MediaPlayer;
import android.net.Uri;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.RotateAnimation;
import net.simplifiedcoding.detectoutgoingcalls.R;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* View that draws, takes keystrokes, etc. for a simple LunarLander game.
* <p/>
* Has a mode which RUNNING, PAUSED, etc. draw() renders the
* ship, and does an invalidate() to prompt another draw() as soon as possible
* by the system.
*/
public class RotaryDialerView extends View {
private float rotorAngle = 0F;
private final Drawable rotorDrawable;
private final int r1 = 50;
private final int r2 = 160;
private double lastFi;
private int startN;
public MediaPlayer mPlayer;
private int width;
private int height;
private boolean soundRotating;
android.media.MediaPlayer.OnCompletionListener soundListener;
private boolean playSound;
MainActivity activity = new MainActivity();
public RotaryDialerView(Context context) {
this(context, null);
soundListener = new android.media.MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mediaplayer) {
stop();
}
};
}
public RotaryDialerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RotaryDialerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
playSound = false;
startN = -1;
soundRotating = false;
rotorDrawable = context.getResources().getDrawable(R.drawable.dialer);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int availableWidth = getRight() - getLeft();
int availableHeight = getBottom() - getTop();
int x = availableWidth / 2;
int y = availableHeight / 2;
canvas.save();
rotorDrawable.setBounds(0, 0, rotorDrawable.getIntrinsicWidth(),
rotorDrawable.getIntrinsicHeight());
if (rotorAngle != 0) {
canvas.rotate(rotorAngle, x, y);
}
rotorDrawable.draw(canvas);
canvas.restore();
}
protected void onMeasure(int i, int j) {
height = android.view.View.MeasureSpec.getSize(j);
width = android.view.View.MeasureSpec.getSize(i);
setMeasuredDimension(width, height);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
final float x0 = width / 2;
final float y0 = height / 2;
float x1 = event.getX();
float y1 = event.getY();
float x = x0 - x1;
float y = y0 - y1;
double r = Math.sqrt(x * x + y * y);
double sinfi = y / r;
double fi = Math.toDegrees(Math.asin(sinfi));
if (x1 > x0 && y0 > y1) {
fi = 180D - fi;
} else if (x1 > x0 && y1 > y0) {
fi = 180D - fi;
} else if (x0 > x1 && y1 > y0) {
fi += 360D;
}
boolean isComplete = false;
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
Log.e("MotionEvent.ACTION_MOVE", "" + MotionEvent.ACTION_MOVE);
if (r > r1 && r < r2) {
if (!soundRotating) {
soundRotating = true;
playSound(startN);
}
final float angle2 = rotorAngle % 360;
int number2 = Math.round(angle2 - 20) / 30;
rotorAngle += Math.abs(fi - lastFi) + 0.25f;
rotorAngle %= 360F;
lastFi = fi;
if (startN >= 10 && !isComplete) {
isComplete = true;
}
// if (number2 < startN || startN == 0 && !isComplete) {
invalidate();
//}
return false;
}
case MotionEvent.ACTION_DOWN:
// playMusic();
// mPlayer2.pause();
calculateStartN(rotorAngle);
rotorAngle = 0F;
lastFi = fi;
return true;
// }
//return false;
case MotionEvent.ACTION_UP:
//mPlayer2.pause();
soundRotating = false;
final float angle = rotorAngle % 360;
int number = Math.round(angle - 20) / 30;
playSound_2(number);
final float fl22 = Math.round(angle - 20) - number * 30;
Log.e("angle", "" + fl22);
if (number > 0) {
if (number == 10) {
number = 0;
}
// if (fl2 < 8.0 && fl2 > 4.0) {
fireDialListenerEvent(number);
//return true;
//}
}
rotorAngle = 0F;
post(new Runnable() {
public void run() {
float fromDegrees = angle;
Animation anim = new RotateAnimation(fromDegrees, 0, Animation.RELATIVE_TO_SELF, 0.5F, Animation.RELATIVE_TO_SELF, 0.5F);
anim.setInterpolator(AnimationUtils.loadInterpolator(getContext(), android.R.anim.decelerate_interpolator));
anim.setAnimationListener(animListener);
anim.setDuration((long) (angle * 5F));
startAnimation(anim);
// playSound();
// angle = 00;//x0;
}
});
startN = -1;
isComplete = false;
return true;
default:
break;
}
return super.onTouchEvent(event);
}
public interface DialListener {
void onDial(int number);
}
private final List<DialListener> dialListeners = new ArrayList<DialListener>();
public void addDialListener(DialListener listener) {
dialListeners.add(listener);
}
public void removeDialListener(DialListener listener) {
dialListeners.remove(listener);
}
private void fireDialListenerEvent(int number) {
for (DialListener listener : dialListeners) {
listener.onDial(number);
Log.e("position ", "Reached");
}
}
private android.view.animation.Animation.AnimationListener animListener = new android.view.animation.Animation.AnimationListener() {
public void onAnimationEnd(Animation animation) {
activity.stopVibrate();
}
public void onAnimationRepeat(Animation animation) {
}
public void onAnimationStart(Animation animation) {
}
};
public void playSound(int n) {
try {
Log.e("n value is", "" + n);
boolean mStartPlaying = true;
if (mStartPlaying == true) {
mPlayer = new MediaPlayer();
Uri uri = Uri.parse("android.resource://net.simplifiedcoding.detectoutgoingcalls/" + activity.SOUNDS_R[n]);
mPlayer.setOnCompletionListener(soundListener);
mPlayer.setDataSource(getContext(), uri);
mPlayer.prepare();
mPlayer.setLooping(false);
mPlayer.start();
} else {
// stopPlaying();
//rePlay.setText("Replay");
mPlayer.stop();
mPlayer.release();
mPlayer = null;
}
mStartPlaying = !mStartPlaying;
} catch (IOException e) {
Log.e("ERR", "prepare() failed");
}
}
public void playSound_2(int n) {
try {
boolean mStartPlaying = true;
if (mStartPlaying == true) {
mPlayer = new MediaPlayer();
Uri uri = Uri.parse("android.resource://net.simplifiedcoding.detectoutgoingcalls/" + activity.SOUNDS_S[n]);
mPlayer.setOnCompletionListener(soundListener);
mPlayer.setDataSource(getContext(), uri);
mPlayer.prepare();
mPlayer.setLooping(false);
mPlayer.start();
} else {
// stopPlaying();
//rePlay.setText("Replay");
mPlayer.stop();
mPlayer.release();
mPlayer = null;
}
mStartPlaying = !mStartPlaying;
} catch (IOException e) {
Log.e("ERR", "prepare() failed");
}
}
public void stop() {
try {
mPlayer.release();
mPlayer.stop();
return;
}
// Misplaced declaration of an exception variable
catch (Exception mediaplayer) {
return;
}
}
private void calculateStartN(double d) {
if (d >= 0.0D && d < 30D) {
startN = 5;
} else {
if (d >= 30D && d < 60D) {
startN = 4;
return;
}
if (d >= 60D && d < 90D) {
startN = 3;
return;
}
if (d >= 90D && d < 120D) {
startN = 2;
return;
}
if (d >= 120D && d <= 150D) {
startN = 1;
return;
}
if (d >= 210D && d < 240D) {
startN = 0;
return;
}
if (d >= 240D && d < 270D) {
startN = 9;
return;
}
if (d >= 270D && d < 300D) {
startN = 8;
return;
}
if (d >= 300D && d < 330D) {
startN = 7;
return;
}
if (d >= 330D && d <= 360D) {
startN = 6;
return;
}
}
}
}
The problem is when i rotate the dialer number it is not stooped when it reach the point.it rotate contentiously with out end.
here is the sample source code
http://www.ssaurel.com/blog/how-to-create-a-rotary-dialer-application-for-android/
every thing is perfect but the only issue is rotation is not stoped when it reach the end
The wheel View (CircleView) is working fine in major of devices but this error coming from S4 and Note 3 devices.
The touch is getting deducted but the that not fall under the weidgetregion.
false - 1 has to be true - 1
Region Log is:
My Circle View code is
public class CircleView extends View implements OnTouchListener{
boolean firstTime = false;
private List<CircleViewBean> mMenuEntries = new ArrayList<CircleViewBean>();
private OnCellTouchListener mOnCellTouchListener = null;
public interface OnCellTouchListener {
public void onTouch(Wedge cell);
}
private Shader mShader;
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
private float screen_density = getContext().getResources().getDisplayMetrics().density;
//Radius of inner ring size
private int mMinSize = scalePX(60);
//Radius of outer ring size
private int mMaxSize = scalePX(170);
private int mWedgeQty = 6;
//Center X location of Radial Menu
private int xPosition = scalePX(120);
//Center Y location of Radial Menu
private int yPosition = scalePX(120);
int touchIndex = -1;
private Wedge[] mWedges;
private RectF mViewRect = new RectF();
private int scalePX( int dp_size )
{
return (int) (dp_size * screen_density + 0.5f);
}
public CircleView(Context context) {
this(context, null);
}
public CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
HashMap<String, String> device = Constants.getDeviceDetails(getResources().getDisplayMetrics().heightPixels, getResources().getDisplayMetrics().widthPixels);
mMinSize = Integer.parseInt(device.get("in_arc"));
mMaxSize = Integer.parseInt(device.get("out_arc"));
setBackgroundResource(R.drawable.centre_wheel);
}
private void determineWedges() {
int entriesQty = mMenuEntries.size();
if ( entriesQty > 0) {
mWedgeQty = entriesQty;
float degSlice = 360 / mWedgeQty;
float start_degSlice = 270 - (degSlice/2);
//calculates where to put the images
this.mWedges = new Wedge[mWedgeQty];
double mid = 0, min = 0, max = 0;
for(int i = 0; i < this.mWedges.length; i++) {
this.mWedges[i] = new Wedge(xPosition, yPosition, mMinSize, mMaxSize, (i
* degSlice)+start_degSlice, degSlice, mMenuEntries.get(i).getIndex());
mid = this.mWedges[i].midValue = normalizeAngle( ((i * degSlice) + start_degSlice + degSlice) / 2 );
min = normalizeAngle( (i * degSlice) + start_degSlice );
max = normalizeAngle( (i * degSlice) + start_degSlice + degSlice);
this.mWedges[i].minValue = min;
this.mWedges[i].midValue = mid;
this.mWedges[i].maxValue = max;
mViewRect.union( new RectF( mWedges[i].getWedgeRegion().getBounds() ) );
}
mShader = new RadialGradient(xPosition, yPosition, mMaxSize, new int[] { 0xff595756, 0xffCCC5C3, 0xf878280}, null, Shader.TileMode.MIRROR);
invalidate();
}
}
#Override
public void onDraw(Canvas canvas) {
if(!firstTime){
firstTime = true;
this.xPosition = (int) (getWidth()/2f);
this.yPosition = (int) (getHeight()/2f);
determineWedges();
}
canvas.scale(getWidth() / mViewRect.width(), getHeight() / mViewRect.width(), xPosition, yPosition);
//Saving the canvas and later restoring it so only this image will be rotated.
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.restore();
canvas.save();
canvas.restore();
mPaint.setShader( mShader );
}
private double normalizeAngle(double angle) {
if(angle >= 0) {
while( angle > 360 ) {
angle -= 360;
}
}
else {
while( angle < -360) {
angle += 360;
}
}
return angle;
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
int wmode = MeasureSpec.getMode(widthMeasureSpec);
int hmode = MeasureSpec.getMode(heightMeasureSpec);
int wsize = MeasureSpec.getSize(widthMeasureSpec);
int hsize = MeasureSpec.getSize(heightMeasureSpec);
int width = (int)mViewRect.width();
int height = (int) mViewRect.height();
if (wmode == MeasureSpec.EXACTLY) {
width = wsize;
}
if (hmode == MeasureSpec.EXACTLY) {
height = hsize;
}
this.setMeasuredDimension(width, height);
invalidate();
}
public class Wedge extends Path {
private int x, y;
private int InnerSize, OuterSize;
private float StartArc;
private float ArcWidth;
private Region mWedgeRegion;
private int index=0;
public double minValue;
public double midValue;
public double maxValue;
private Wedge(int x, int y, int InnerSize, int OuterSize, float StartArc, float ArcWidth, int category) {
super();
this.index = category;
if (StartArc >= 360) {
StartArc = StartArc-360;
}
minValue = midValue = maxValue = 0;
mWedgeRegion = new Region();
this.x = x; this.y = y;
this.InnerSize = InnerSize;
this.OuterSize = OuterSize;
this.StartArc = StartArc;
this.ArcWidth = ArcWidth;
this.buildPath();
}
public int getCategoryIndex(){
return this.index;
}
public String toString() {
return minValue + " " + midValue + " " + maxValue;
}
/**
*
* #return the bottom rect that will be used for intersection
*/
public Region getWedgeRegion() {
return mWedgeRegion;
}
private void buildPath() {
final RectF rect = new RectF();
final RectF rect2 = new RectF();
//Rectangles values
rect.set(this.x-this.InnerSize, this.y-this.InnerSize, this.x+this.InnerSize, this.y+this.InnerSize);
rect2.set(this.x-this.OuterSize, this.y-this.OuterSize, this.x+this.OuterSize, this.y+this.OuterSize);
this.reset();
//this.moveTo(100, 100);
this.arcTo(rect2, StartArc, ArcWidth);
this.arcTo(rect, StartArc+ArcWidth, -ArcWidth);
this.close();
mWedgeRegion.setPath( this, new Region(0,0,480,800) );
}
}
public boolean addMenuEntry(CircleViewBean menuEntry) {
mMenuEntries.add(menuEntry);
return true;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP){
if(mOnCellTouchListener!=null && touchIndex >-1){
int i=0;
for(Wedge day : mWedges) {
if(day.getWedgeRegion().getBounds().contains((int)event.getX(), (int)event.getY()) && touchIndex==i) {
mOnCellTouchListener.onTouch(mWedges[touchIndex]);
break;
}
i++;
}
}
}else if(event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE){
int i=0;
for(Wedge day : mWedges) {
if(day.getWedgeRegion().getBounds().contains((int)event.getX(), (int)event.getY())) {
touchIndex = i;
setBackgroundResource(mMenuEntries.get(touchIndex).getIcon());
}
i++;
}
}
return true;
}
public void setOnCellTouchListener(OnCellTouchListener p) {
mOnCellTouchListener = p;
}
public boolean onTouch(View v, MotionEvent event) {
return false;
}
}
First of all, look at line 307. Learn how to read crash logs because it says exactly on what line the crash is, and then it shouldn't be too hard too determine what is wrong.
Not knowing what line it is I guess that mWedges might be null. in the onTouch you do for(Wedge day : mWedges) but it is not guaranteed that is isn't null there. You should check before you do that if it is null.
You put it to a non null value in determineWedges but only when there is at least 1 mMenuEntries. So when there are no entries when you do an onTouch it will crash.
At last i found my mistake in this code that it is working in mdpi and htpi and not in xxhdpi the reason is
mWedgeRegion.setPath( this, new Region(0,0,480,800) );
The bound exceeds the circle size, i mean the xxhdpi draws an circle with 1000x1000 values, so i made this too like this (max values)
mWedgeRegion.setPath( this, new Region(0,0,720,1200) )
I had tried alot & even search alot but i didn't found
the solution about the black screen
which i get by fetching the cache view on the surface view..
if is there any other way to capture the screen then let me know about this..
if i use another control & fetching the drawable cache of that control it also return null..
this is the code which i used to fetch the screen Image....
try {
// Button btn = new Button(mActivity.getApplicationContext());
view.buildDrawingCache();
view.setDrawingCacheEnabled(true);
Bitmap b = view.getDrawingCache();
b.compress(CompressFormat.JPEG, 100, new FileOutputStream(
"/mnt/sdcard/documents/" + new Date().getTime() + ".JPEG"));
} catch (Exception e) {
e.printStackTrace();
}
i had used this on the touch_up action of the surface view.....
EDIT:
public class DroidReaderActivity extends Activity {
private static final boolean LOG = false;
private static final int REQUEST_CODE_PICK_FILE = 1;
private static final int REQUEST_CODE_OPTION_DIALOG = 2;
private static final int DIALOG_GET_PASSWORD = 1;
private static final int DIALOG_ABOUT = 2;
private static final int DIALOG_GOTO_PAGE = 3;
private static final int DIALOG_WELCOME = 4;
private static final int DIALOG_ENTER_ZOOM = 5;
private static final String PREFERENCE_EULA_ACCEPTED = "eula.accepted";
private static final String PREFERENCES_EULA = "eula";
protected DroidReaderView mReaderView = null;
protected DroidReaderDocument mDocument = null;
protected Menu m_ZoomMenu;
FrameLayout fl;
private String mFilename;
private String mTemporaryFilename;
private String mPassword;
private int mPageNo;
private SQLiteDatabase db;
static DatabaseConnectionAPI db_api;
private boolean mDocumentIsOpen = false;
private boolean mLoadedDocument = false;
private boolean mWelcomeShown = false;
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_CODE_PICK_FILE:
if (resultCode == RESULT_OK && data != null) {
// Theoretically there could be a case where OnCreate() is called
// again with the intent that was originally used to open the app,
// which would revert to a previous document. Use setIntent
// to update the intent that will be supplied back to OnCreate().
setIntent(data);
mTemporaryFilename = data.getDataString();
if (mTemporaryFilename != null) {
if (mTemporaryFilename.startsWith("file://")) {
mTemporaryFilename = mTemporaryFilename.substring(7);
}
mPassword = "";
openDocumentWithDecodeAndLookup();
}
}
break;
case REQUEST_CODE_OPTION_DIALOG:
readPreferences();
tryLoadLastFile();
break;
}
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.out.println("ONCREATE");
db_api = new DatabaseConnectionAPI(this);
try {
db_api.createDataBase();
db_api.openDataBase();
} catch (IOException e) {
e.printStackTrace();
}
// first, show the welcome if it hasn't been shown already:
final SharedPreferences preferences = getSharedPreferences(PREFERENCES_EULA, Context.MODE_PRIVATE);
if (!preferences.getBoolean(PREFERENCE_EULA_ACCEPTED, false)) {
mWelcomeShown = true;
preferences.edit().putBoolean(PREFERENCE_EULA_ACCEPTED, true).commit();
showDialog(DIALOG_WELCOME);
}
if (mDocument == null)
mDocument = new DroidReaderDocument();
// Initialize the PdfRender engine
PdfRender.setFontProvider(new DroidReaderFontProvider(this));
// then build our layout. it's so simple that we don't use
// XML for now.
fl = new FrameLayout(this);
mReaderView = new DroidReaderView(this, null, mDocument);
// add the viewing area and the navigation
fl.addView(mReaderView);
setContentView(fl);
readPreferences();
if (savedInstanceState != null) {
mFilename = savedInstanceState.getString("filename");
if ((new File(mFilename)).exists()) {
mPassword = savedInstanceState.getString("password");
mDocument.mZoom = savedInstanceState.getFloat("zoom");
mDocument.mRotation = savedInstanceState.getInt("rotation");
mPageNo = savedInstanceState.getInt("page");
mDocument.mMarginOffsetX = savedInstanceState.getInt("marginOffsetX");
mDocument.mMarginOffsetY = savedInstanceState.getInt("marginOffsetY");
mDocument.mContentFitMode = savedInstanceState.getInt("contentFitMode");
openDocument();
mLoadedDocument = true;
}
savedInstanceState.clear();
}
Timer mTimer = new Timer();
mTimer.schedule(new TimerTask() {
#Override
public void run() {
try {
Bitmap saveBitmap = Bitmap.createBitmap(fl.getWidth(), fl.getHeight(), Bitmap.Config.ARGB_8888);
saveBitmap.compress(CompressFormat.JPEG, 100,
new FileOutputStream("/mnt/sdcard/documents/" + new Date().getTime() + ".JPEG"));
} catch (Exception e) {
e.printStackTrace();
}
}
}, 4000);
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if ((mDocument != null) && mDocument.isPageLoaded()) {
outState.putFloat("zoom", mDocument.mZoom);
outState.putInt("rotation", mDocument.mRotation);
outState.putInt("page", mDocument.mPage.no);
outState.putInt("offsetX", mDocument.mOffsetX);
outState.putInt("offsetY", mDocument.mOffsetY);
outState.putInt("marginOffsetX", mDocument.mMarginOffsetX);
outState.putInt("marginOffsetY", mDocument.mMarginOffsetY);
outState.putInt("contentFitMode", mDocument.mContentFitMode);
outState.putString("password", mPassword);
outState.putString("filename", mFilename);
mDocument.closeDocument();
}
}
public void onTap(float X, float Y) {
float left, right, top, bottom;
float width = mDocument.mDisplaySizeX;
float height = mDocument.mDisplaySizeY;
boolean prev = false;
boolean next = false;
if (mDocumentIsOpen) {
left = width * (float) 0.25;
right = width * (float) 0.75;
top = height * (float) 0.25;
bottom = height * (float) 0.75;
if ((X < left) && (Y < top))
prev = true;
if ((X < left) && (Y > bottom))
next = true;
if ((X > right) && (Y < top))
prev = true;
if ((X > right) && (Y > bottom))
next = true;
if ((X > left) && (X < right) && (Y > bottom)) {
Log.d("DroidReaderMetrics", String.format("Zoom = %5.2f%%", mDocument.mZoom * 100.0));
Log.d("DroidReaderMetrics", String.format("Page size = (%2.0f,%2.0f)", mDocument.mPage.mMediabox[2]
- mDocument.mPage.mMediabox[0], mDocument.mPage.mMediabox[3] - mDocument.mPage.mMediabox[1]));
Log.d("DroidReaderMetrics", String.format(
"Display size = (%d,%d)", mDocument.mDisplaySizeX, mDocument.mDisplaySizeY));
Log.d("DroidReaderMetrics", String.format("DPI = (%d, %d)", mDocument.mDpiX, mDocument.mDpiY));
Log.d("DroidReaderMetrics", String.format("Content size = (%2.0f,%2.0f)",
mDocument.mPage.mContentbox[2] - mDocument.mPage.mContentbox[0],
mDocument.mPage.mContentbox[3] - mDocument.mPage.mContentbox[1]));
Log.d("DroidReaderMetrics", String.format("Content offset = (%2.0f,%2.0f)",
mDocument.mPage.mContentbox[0], mDocument.mPage.mContentbox[1]));
Log.d("DroidReaderMetrics", String.format(
"Document offset = (%d,%d)", mDocument.mOffsetX, mDocument.mOffsetY));
}
if (next) {
if (mDocument.havePage(1, true))
openPage(1, true);
} else if (prev) {
if (mDocument.havePage(-1, true))
openPage(-1, true);
}
}
}
protected void openDocument() {
// Store the view details for the previous document and close it.
if (mDocumentIsOpen) {
mDocument.closeDocument();
mDocumentIsOpen = false;
}
try {
this.setTitle(mFilename);
mDocument.open(mFilename, mPassword, mPageNo);
openPage(0, true);
mDocumentIsOpen = true;
} catch (PasswordNeededException e) {
showDialog(DIALOG_GET_PASSWORD);
} catch (WrongPasswordException e) {
Toast.makeText(this, R.string.error_wrong_password, Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(this, R.string.error_opening_document, Toast.LENGTH_LONG).show();
}
}
protected void openDocumentWithDecodeAndLookup() {
try {
mTemporaryFilename = URLDecoder.decode(mTemporaryFilename, "utf-8");
// Do some sanity checks on the supplied filename.
File f = new File(mTemporaryFilename);
if ((f.exists()) && (f.isFile()) && (f.canRead())) {
mFilename = mTemporaryFilename;
openDocumentWithLookup();
} else {
Toast.makeText(this, R.string.error_file_open_failed, Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
Toast.makeText(this, R.string.error_opening_document, Toast.LENGTH_LONG).show();
}
}
protected void openDocumentWithLookup() {
readOrWriteDB(false);
openDocument();
}
protected void openPage(int no, boolean isRelative) {
try {
if (!(no == 0 && isRelative))
mDocument.openPage(no, isRelative);
this.setTitle(new File(mFilename).getName()
+ String.format(" (%d/%d)", mDocument.mPage.no, mDocument.mDocument.pagecount));
mPageNo = mDocument.mPage.no;
} catch (PageLoadException e) {
}
}
private void readPreferences() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
if (prefs.getString("zoom_type", "0").equals("0")) {
float zoom = Float.parseFloat(prefs.getString("zoom_percent", "50"));
if ((1 <= zoom) && (1000 >= zoom)) {
mDocument.setZoom(zoom / 100, false);
}
} else {
mDocument.setZoom(Float.parseFloat(prefs.getString("zoom_type", "0")), false);
}
if (prefs.getBoolean("dpi_auto", true)) {
// read the display's DPI
mDocument.setDpi((int) metrics.xdpi, (int) metrics.ydpi);
} else {
int dpi = Integer.parseInt(prefs.getString("dpi_manual", "160"));
if ((dpi < 1) || (dpi > 4096))
dpi = 160; // sanity check fallback
mDocument.setDpi(dpi, dpi);
}
if (prefs.getBoolean("tilesize_by_factor", true)) {
// set the tile size for rendering by factor
Float factor = Float.parseFloat(prefs.getString("tilesize_factor", "1.5"));
mDocument.setTileMax((int) (metrics.widthPixels * factor), (int) (metrics.heightPixels * factor));
} else {
int tilesize_x = Integer.parseInt(prefs.getString("tilesize_x", "640"));
int tilesize_y = Integer.parseInt(prefs.getString("tilesize_x", "480"));
if (metrics.widthPixels < metrics.heightPixels) {
mDocument.setTileMax(tilesize_x, tilesize_y);
} else {
mDocument.setTileMax(tilesize_y, tilesize_x);
}
}
boolean invert = prefs.getBoolean("invert_display", false);
mDocument.setDisplayInvert(invert);
mReaderView.setDisplayInvert(invert);
if (prefs.getBoolean("full_screen", false)) {
this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
} else {
this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
mDocument.mHorizontalScrollLock = prefs.getBoolean("horizontal_scroll_lock", false);
}
protected void setZoom(float newZoom) {
newZoom = newZoom / (float) 100.0;
if (newZoom > 16.0)
newZoom = (float) 16.0;
if (newZoom < 0.0625)
newZoom = (float) 0.0625;
mDocument.setZoom(newZoom, false);
}
protected void tryLoadLastFile() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
mFilename = prefs.getString("last_open_file", "");
if (mFilename != null) {
if ((mFilename.length() > 0) && ((new File(mFilename)).exists())) {
// Don't URL-decode the filename, as that's presumably already been done.
mPassword = "";
openDocumentWithLookup();
mLoadedDocument = true;
}
}
}
}
DroidReaderView:
public class DroidReaderView extends SurfaceView implements OnGestureListener,
SurfaceHolder.Callback, DroidReaderDocument.RenderListener {
public static Path mPath = new Path();
private static StringBuffer sbx = new StringBuffer();
private static StringBuffer sby = new StringBuffer();
public static Paint mPaint = new Paint();
public static Paint nullpaint = new Paint();
private String sx, sy, sbx_str, sby_str;
public static Canvas mCanvas = new Canvas();
private int pid = 1;
/**
* Debug helper
*/
protected final static String TAG = "DroidReaderView";
protected final static boolean LOG = false;
/**
* our view thread which does the drawing
*/
public DroidReaderViewThread mThread;
/**
* our gesture detector
*/
protected final GestureDetector mGestureDetector;
/**
* our context
*/
protected final DroidReaderActivity mActivity;
/**
* our SurfaceHolder
*/
protected final SurfaceHolder mSurfaceHolder;
public static DroidReaderDocument mDocument;
protected boolean mDisplayInvert;
/**
* constructs a new View
*
* #param context
* Context for the View
* #param attrs
* attributes (may be null)
*/
public DroidReaderView(final DroidReaderActivity activity, AttributeSet attrs, DroidReaderDocument document) {
super(activity, attrs);
mActivity = activity;
mSurfaceHolder = getHolder();
mDocument = document;
mDocument.mRenderListener = this;
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);
// tell the SurfaceHolder to inform this thread on
// changes to the surface
mSurfaceHolder.addCallback(this);
mGestureDetector = new GestureDetector(this);
}
/* event listeners: */
#Override
protected void onDraw(Canvas canvas) {
mThread.c = canvas;
mThread.c = mSurfaceHolder.lockCanvas();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);
mThread.c.drawPath(mPath, mPaint);
mSurfaceHolder.unlockCanvasAndPost(mThread.c);
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if (LOG)
Log.d(TAG, "onFling(): notifying ViewThread");
mThread.mScroller.fling(0, 0, -(int) velocityX, -(int) velocityY, -4096, 4096, -4096, 4096);
mThread.triggerRepaint();
return true;
}
/* keyboard events: */
#Override
public boolean onKeyDown(int keyCode, KeyEvent msg) {
if (LOG)
Log.d(TAG, "onKeyDown(), keycode " + keyCode);
return false;
}
#Override
public boolean onKeyUp(int keyCode, KeyEvent msg) {
if (LOG)
Log.d(TAG, "onKeyUp(), keycode " + keyCode);
return false;
}
/* interface for the GestureListener: */
#Override
public void onLongPress(MotionEvent e) {
if (LOG)
Log.d(TAG, "onLongPress(): ignoring!");
}
#Override
public void onNewRenderedPixmap() {
if (LOG)
Log.d(TAG, "new rendered pixmap was signalled");
mThread.triggerRepaint();
}
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
if (LOG)
Log.d(TAG, "onScroll(), distance vector: " + distanceX + "," + distanceY);
mDocument.offset((int) distanceX, (int) distanceY, true);
mThread.triggerRepaint();
return true;
}
#Override
public void onShowPress(MotionEvent e) {
if (LOG)
Log.d(TAG, "onShowPress(): ignoring!");
}
#Override
public boolean onSingleTapUp(MotionEvent e) {
// Pass the tap, and the window dimensions, to the activity to process.
mActivity.onTap(e.getX(), e.getY());
return true;
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
mPath.moveTo(x, y);
mX = x;
sx = Float.toString(mX);
sbx.append(sx);
sbx.append(",");
mY = y;
sy = Float.toString(mY);
sby.append(sy);
sby.append(",");
sbx_str = sbx.toString();
sby_str = sby.toString();
}
private void draw_move(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
sx = Float.toString(mX);
sbx.append(sx);
sbx.append(",");
mY = y;
sy = Float.toString(mY);
sby.append(sy);
sby.append(",");
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
sx = Float.toString(mX);
sbx.append(sx);
sbx.append(",");
sy = Float.toString(mY);
sby.append(sy);
sby.append(",");
mPath.reset();
sbx_str = sbx.toString().trim();
sby_str = sby.toString().trim();
insert(TAGS.presentation_id, mDocument.mPage.no, sbx_str, sby_str);
sbx = new StringBuffer();
sby = new StringBuffer();
System.out.println(sbx_str.trim());
System.out.println(sby_str.trim());
}
#Override
public boolean onTouchEvent(final MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
draw_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
try {
// Button btn = new Button(mActivity.getApplicationContext());
// buildDrawingCache();
// setDrawingCacheEnabled(true);
// Bitmap b = getDrawingCache();
// b.compress(CompressFormat.JPEG, 100, new FileOutputStream(
// "/mnt/sdcard/documents/" + new Date().getTime() + ".JPEG"));
} catch (Exception e) {
e.printStackTrace();
}
break;
}
invalidate();
if (LOG) {
Log.d(TAG, "onTouchEvent(): notifying mGestureDetector");
invalidate();
}
if (mGestureDetector.onTouchEvent(event)) {
invalidate();
return true;
}
return true;
}
#Override
public boolean onTrackballEvent(MotionEvent event) {
if (LOG)
Log.d(TAG, "onTouchEvent(): notifying ViewThread");
mDocument
.offset((int) event.getX() * 20, (int) event.getY() * 20, true);
mThread.triggerRepaint();
return true;
}
/* surface events: */
public void setDisplayInvert(boolean invert) {
if (mThread != null)
mThread.setPainters(invert);
mDisplayInvert = invert;
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if (LOG)
Log.d(TAG, "surfaceChanged(): size " + width + "x" + height);
mDocument.startRendering(width, height);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (LOG)
Log.d(TAG, "surfaceCreated(): starting ViewThread");
mThread = new DroidReaderViewThread(holder, mActivity, mDocument);
mThread.setPainters(mDisplayInvert);
mThread.start();
}
/* render events */
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (LOG)
Log.d(TAG, "surfaceDestroyed(): dying");
mDocument.stopRendering();
boolean retry = true;
mThread.mRun = false;
mThread.interrupt();
while (retry) {
try {
mThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
#Override
public boolean onDown(MotionEvent e) {
return false;
}
DroidReaderViewThread :
Thread that cares for blitting Pixmaps onto the Canvas and handles scrolling
class DroidReaderViewThread extends Thread {
public Canvas c = new Canvas();
private Cursor mCursor;
private Path mPath1 = new Path();
private StringBuffer sbx_read, sby_read;
public static Paint mPaint2 = new Paint();
public static Paint mPaint3 = new Paint();
Path old_path = new Path();
/**
* Debug helper
*/
protected final static String TAG = "DroidReaderViewThread";
protected final static boolean LOG = false;
/**
* the SurfaceHolder for our Surface
*/
protected final SurfaceHolder mSurfaceHolder;
/**
* Paint for not (yet) rendered parts of the page
*/
protected final Paint mEmptyPaint;
/**
* Paint for filling the display when there is no PdfPage (yet)
*/
protected final Paint mNoPagePaint;
/**
* Paint for the status text
*/
protected final Paint mStatusPaint;
/**
* Flag that our thread should be running
*/
protected boolean mRun = true;
/**
* our scroller
*/
protected final Scroller mScroller;
protected final DroidReaderDocument mDocument;
/**
* Background render thread, using the SurfaceView programming scheme
*
* #param holder
* our SurfaceHolder
* #param context
* the Context for our drawing
*/
public DroidReaderViewThread(SurfaceHolder holder, Context context, DroidReaderDocument document) {
// store a reference to our SurfaceHolder
mSurfaceHolder = holder;
mDocument = document;
// initialize Paints for non-Pixmap areas
mEmptyPaint = new Paint();
mNoPagePaint = new Paint();
mStatusPaint = new Paint();
setPainters(false);
// the scroller, i.e. the object that calculates/interpolates
// positions for scrolling/jumping/flinging
mScroller = new Scroller(context);
}
/**
* ll this does the actual drawing to the Canvas for our surface
*/
private void doDraw() {
if (LOG)
Log.d(TAG, "drawing...");
c = null;
try {
c = mSurfaceHolder.lockCanvas(null);
if (!mDocument.isPageLoaded()) {
// no page/document loaded
if (LOG)
Log.d(TAG, "no page loaded.");
c.drawRect(0, 0, c.getWidth(), c.getHeight(), mNoPagePaint);
} else if (mDocument.havePixmap()) {
// we have both page and Pixmap, so draw:
// background:
if (LOG)
Log.d(TAG, "page loaded, rendering pixmap");
c.drawRect(0, 0, c.getWidth(), c.getHeight(), mEmptyPaint);
Log.d("CALL", "CALL");
c.drawBitmap(mDocument.mView.mBuf, 0,
mDocument.mView.mViewBox.width(), -mDocument.mOffsetX + mDocument.mView.mViewBox.left,
-mDocument.mOffsetY + mDocument.mView.mViewBox.top,
mDocument.mView.mViewBox.width(), mDocument.mView.mViewBox.height(), false, null);
try {
Log.d("Reading", "Reading");
mCursor = DroidReaderActivity.db_api
.ExecuteQueryGetCursor("SELECT * FROM path WHERE page_no=" + mDocument.mPage.no
+ " AND presentation_id=" + TAGS.presentation_id + ";");
if (!mCursor.equals(null)) {
mCursor.moveToFirst();
float x1 = 0, y1 = 0;
int pid = 0;
do {
sbx_read = new StringBuffer();
sbx_read.append(mCursor.getString(mCursor.getColumnIndex("x_path")));
sby_read = new StringBuffer();
sby_read.append(mCursor.getString(mCursor.getColumnIndex("y_path")));
String[] sbx_read_array = sbx_read.toString().trim().split(",");
String[] sby_read_array = sby_read.toString().trim().split(",");
for (int i = 0; i < sbx_read_array.length; i++) {
x1 = Float.parseFloat(sbx_read_array[i].toString());
y1 = Float.parseFloat(sby_read_array[i].toString());
if (pid != mCursor.getInt(mCursor.getColumnIndex("path_id"))) {
pid = mCursor.getInt(mCursor.getColumnIndex("path_id"));
Log.d("New Path Id.",
String.valueOf(mCursor.getInt(mCursor.getColumnIndex("path_id"))));
mPath1.reset();
mPath1.moveTo(x1, y1);
} else {
Log.d("Path id repeating.",
String.valueOf(mCursor.getInt(mCursor.getColumnIndex("path_id"))));
}
mPath1.lineTo(x1, y1);
c.drawPath(mPath1, DroidReaderView.mPaint);
}
} while (mCursor.moveToNext());
mCursor.close();
Log.d("Read mode Complete", "Read mode Complete");
}
} catch (Exception e) {
// Log.d("read Cursor", e.getMessage().toString());
}
} else {
// page loaded, but no Pixmap yet
if (LOG)
Log.d(TAG, "page loaded, but no active Pixmap.");
c.drawRect(0, 0, c.getWidth(), c.getHeight(), mEmptyPaint);
mPaint3.setAntiAlias(true);
mPaint3.setDither(true);
mPaint3.setColor(Color.TRANSPARENT);
mPaint3.setStyle(Paint.Style.STROKE);
mPaint3.setStrokeJoin(Paint.Join.ROUND);
mPaint3.setStrokeCap(Paint.Cap.ROUND);
mPaint3.setStrokeWidth(12);
mPaint3.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
c.drawPath(old_path, mPaint3);
}
} finally {
if (c != null) {
mPaint2.setAntiAlias(true);
mPaint2.setDither(true);
mPaint2.setColor(Color.GREEN);
mPaint2.setStyle(Paint.Style.STROKE);
mPaint2.setStrokeJoin(Paint.Join.ROUND);
mPaint2.setStrokeCap(Paint.Cap.ROUND);
mPaint2.setStrokeWidth(12);
c.drawPath(DroidReaderView.mPath, mPaint2);
// DroidReaderView.mPath.reset();
// old_path = DroidReaderView.mPath;
}
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
/**
* Main Thread loop
*/
#SuppressWarnings("static-access")
#Override
public void run() {
while (mRun) {
boolean doSleep = true;
if (!mScroller.isFinished()) {
if (mScroller.computeScrollOffset()) {
if (LOG)
Log.d(TAG, "new scroll offset");
doSleep = false;
int oldX = mDocument.mOffsetX;
int oldY = mDocument.mOffsetY;
mDocument.offset(mScroller.getCurrX(), mScroller.getCurrY(), true);
if ((oldX == mDocument.mOffsetX) && (oldY == mDocument.mOffsetY))
mScroller.abortAnimation();
} else {
mScroller.abortAnimation();
}
}
doDraw();
// if we're allowed, we will go to sleep now
if (doSleep) {
try {
// nothing to do, wait for someone waking us up:
if (LOG)
Log.d(TAG, "ViewThread going to sleep");
// between
// the check for pending interrupts and the sleep() which
// could lead to a not-handled repaint request:
if (!this.interrupted())
Thread.sleep(3600000);
} catch (InterruptedException e) {
if (LOG)
Log.d(TAG, "ViewThread woken up");
}
}
}
// mRun is now false, so we shut down.
if (LOG)
Log.d(TAG, "shutting down");
}
public void setPainters(boolean invert) {
// initialize Paints for non-Pixmap areas
mEmptyPaint.setStyle(Paint.Style.FILL);
mNoPagePaint.setStyle(Paint.Style.FILL);
mStatusPaint.setStyle(Paint.Style.FILL);
if (invert)
mEmptyPaint.setColor(0xff000000); // black
else
mEmptyPaint.setColor(0xffc0c0c0); // light gray
if (invert)
mNoPagePaint.setColor(0xff000000); // black
else
mNoPagePaint.setColor(0xff303030); // dark gray
if (invert)
mStatusPaint.setColor(0xff000000); // black
else
mStatusPaint.setColor(0xff808080); // medium gray
}
public void triggerRepaint() {
if (LOG)
Log.d(TAG, "repaint triggered");
interrupt();
}
}
I am using this, and its works fine in my case,
Here imageFrame is FrameLayout, root view of my View which I want to save as bitmap..
Bitmap saveBitmap = Bitmap.createBitmap(imageFrame.getWidth(), imageFrame.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(saveBitmap);
imageFrame.draw(c);
Try replacing imageFrame with your view.
EDIT:
Date date = new Date();
File filename = new File(file.getAbsoluteFile(), "" + date.getTime() + ".jpg");
try
{
fOut = new FileOutputStream(filename);
saveBitmap.compress(Bitmap.CompressFormat.JPEG, 50, fOut);
try
{
fOut.flush();
fOut.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
EDIT 2:
private void doDraw() {
int w = WIDTH_PX, h = HEIGHT_PX;
BitmapConfig conf = Bitmap.Config.ARGB_8888; // see other conf types
Bitmap bmp = Bitmap.createBitmap(w, h, conf); // this creates a MUTABLE bitmap
c = new Canvas(bmp);