i am using andengine for implementing accelerometer sensor in android. my requirement is i have to move the ball to the center of the screen using accelerometer. I am able to achieve that when the device is in lying flat position. because it uses the X and Y acceleration values for the calculation in AndEngine library.
but the problem arise when i hold the device in straight up position. the object doesn't move to the center and it always lays down to the bottom bar of the screen. however, i tried to calculate the z value at this time and inject my logic into AccelerationData class to use z value instead of y. but no success. please go through the following code and guide me what wrong i am doing.
AccelerationData.java
public class AccelerationData extends BaseSensorData {
// ===========================================================
// Constants
// ===========================================================
private static final IAxisSwap AXISSWAPS[] = new IAxisSwap[4];
static {
AXISSWAPS[Surface.ROTATION_0] = new IAxisSwap() {
#Override
public void swapAxis(final float[] pValues) {
final float x = -pValues[SensorManager.DATA_X];
final float y;
if(SensorManager.DATA_Z > -0.50 && SensorManager.DATA_Z <0.50){
y = pValues[SensorManager.DATA_Z];
}else{
y = pValues[SensorManager.DATA_Y];
}
pValues[SensorManager.DATA_X] = x;
pValues[SensorManager.DATA_Y] = y;
}
};
AXISSWAPS[Surface.ROTATION_90] = new IAxisSwap() {
#Override
public void swapAxis(final float[] pValues) {
final float x = pValues[SensorManager.DATA_Y];
final float y = pValues[SensorManager.DATA_X];
pValues[SensorManager.DATA_X] = x;
pValues[SensorManager.DATA_Y] = y;
}
};
AXISSWAPS[Surface.ROTATION_180] = new IAxisSwap() {
#Override
public void swapAxis(final float[] pValues) {
final float x = pValues[SensorManager.DATA_X];
final float y = -pValues[SensorManager.DATA_Y];
pValues[SensorManager.DATA_X] = x;
pValues[SensorManager.DATA_Y] = y;
}
};
AXISSWAPS[Surface.ROTATION_270] = new IAxisSwap() {
#Override
public void swapAxis(final float[] pValues) {
final float x = -pValues[SensorManager.DATA_Y];
final float y = -pValues[SensorManager.DATA_X];
pValues[SensorManager.DATA_X] = x;
pValues[SensorManager.DATA_Y] = y;
}
};
}
...
...
}
here i am showing the usage of z value only when device is at 0 degree. any help would be greatly appreciated.
Related
I have a class named MapViewManager, in it I have a method called navigate like below:
public class MapViewManager{
...
public void navigate(double startX, double startY, double toX, double toY, long floorId, boolean flag) {
final FeatureLayer featureLayer = new FeatureLayer("navigate");
mapView.setLayerOffset(featureLayer);
mapView.addLayer(featureLayer);
final NavigateManager navigateManager = new NavigateManager();
if (flag) {
navigateManager.navigation(startX, startY, floorId, toX, toY, floorId);
}else{
navigateManager.clear();
}
navigateManager.setOnNavigateComplete(new NavigateManager.OnNavigateComplete() {
#Override
public void onNavigateComplete(NavigateManager.NavigateState navigateState,
FeatureCollection featureCollection) {
featureLayer.clearFeatures();
featureLayer.addFeatures(featureCollection);
for (int i=0;i<featureCollection.getSize();i++){
Feature feature = featureCollection.getFeature(i);
Coordinate coordinate = feature.getCentroid();
double x = coordinate.getX();
double y = coordinate.getY();
}
}
});
}
}
I want to access the variable named coordinate in onNavigateComplete callback method from outside so that other classes can use the coordinate variable to do something. How can I make it?
Add one more parameter to navigate method.
public class MapViewManager{
...
public void navigate(double startX, double startY, double toX, double toY, long floorId, boolean flag, NavigateManager.OnNavigateComplete navigation) {
final FeatureLayer featureLayer = new FeatureLayer("navigate");
mapView.setLayerOffset(featureLayer);
mapView.addLayer(featureLayer);
final NavigateManager navigateManager = new NavigateManager();
if (flag) {
navigateManager.navigation(startX, startY, floorId, toX, toY, floorId);
}else{
navigateManager.clear();
}
navigateManager.setOnNavigateComplete(navigation);
}
}
Call method from other Class :
new MapViewManager().navigate(other paramter values, new NavigateManager.OnNavigateComplete() {
#Override
public void onNavigateComplete(NavigateManager.NavigateState navigateState,
FeatureCollection featureCollection) {
featureLayer.clearFeatures();
featureLayer.addFeatures(featureCollection);
for (int i=0;i<featureCollection.getSize();i++){
Feature feature = featureCollection.getFeature(i);
Coordinate coordinate = feature.getCentroid();
navigationPoints.add(coordinate);
double x = coordinate.getX();
double y = coordinate.getY();
}
}
});
Now you can access any object anywhere.
You have to make it public by doing this:
Say your activity name is 'Main'
....
Public class Main extends AppCompatActivity{
Coordinate coor;
//in the onNavigationComplete method do this
Coordinate coordinate = //..complete this;
coor = coordinate;
…
…}
I want to connect several classes which are functioning separately but are related.
Lets say I am writing an app in which you can swipe to draw a chart. There are lots of classes in the app which are related and should be connected.
For example three of the classes are:
Swiper - responsible for interpreting the gesture of the user
Points - responsible for handling the points on the chart
ChartDrawer - responsible for drawing the chart on the screen
I want to know is there any design pattern such as a connector which can handle the relation and communication of these classes? Any way i can redesign in a better way or make mind more object oriented?
This is my ChartDraw class which extends a view:
public class ChartDraw extends View implements GestureReceiver {
int chartYPosition;
private int circleColor;
private int circleRadius;
int height;
private float lastPointOnChart;
private int lineColor;
private int lineWidth;
private Paint paint;
private float tempPoint;
int width;
public ChartDraw(Context context) {
super(context);
init();
}
public ChartDraw(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ChartDraw(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
this.lineWidth = 15;
this.circleRadius = 20;
this.lineColor = Color.parseColor("#1976D2");
this.circleColor = Color.parseColor("#536DFE");
this.lastPointOnChart = 0.0f;
this.tempPoint = 0.0f;
this.paint = new Paint();
this.height = getHeight();
this.width = getWidth();
this.chartYPosition = this.height / 2;
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
this.chartYPosition = canvas.getHeight() / 2;
this.paint.setStrokeWidth((float) this.lineWidth);
this.paint.setColor(this.lineColor);
canvas.drawLine(0.0f, (float) this.chartYPosition, this.tempPoint, (float) this.chartYPosition, this.paint);
if (this.tempPoint > 20.0f) {
this.paint.setColor(this.circleColor);
canvas.drawCircle(20.0f, (float) this.chartYPosition, 20.0f, this.paint);
drawTriangle(canvas, this.paint, this.tempPoint, this.chartYPosition);
}
}
private void drawTriangle(Canvas canvas, Paint paint, float startX, int startY) {
Path path = new Path();
path.moveTo(startX, (float) (startY - 20));
path.lineTo(startX, (float) (startY + 20));
path.lineTo(30.0f + startX, (float) startY);
path.lineTo(startX, (float) (startY - 20));
path.close();
canvas.drawPath(path, paint);
}
public void onMoveHorizontal(float dx) {
this.tempPoint = this.lastPointOnChart + dx;
invalidate();
}
public void onMoveVertical(float dy) {
}
public void onMovementStop() {
this.lastPointOnChart = this.tempPoint;
}
}
And this is My SwipeManager which is handling user gesture:
public class SwipeManager implements View.OnTouchListener {
GestureReceiver receiver;
private int activePointer;
private float initX,
initY;
private long startTime,
stopTime;
private boolean resolving = false;
private boolean resolved = false;
private Direction direction;
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (receiver == null) throw new AssertionError("You must register a receiver");
switch (motionEvent.getActionMasked()) {
case ACTION_DOWN:
activePointer = motionEvent.getPointerId(0);
initX = motionEvent.getX(activePointer);
initY = motionEvent.getY(activePointer);
startTime = new Date().getTime();
break;
case ACTION_MOVE:
if (!resolving && !resolved) {
resolving = true;
float x = motionEvent.getX(activePointer);
float y = motionEvent.getY(activePointer);
direction = resolveDirection(x, y);
if (direction != Direction.STILL) {
resolved = true;
resolving = false;
} else {
resolving = false;
resolved = false;
}
break;
}
if (resolved) {
if (direction == Direction.HORIZONTAL)
receiver.onMoveHorizontal(motionEvent.getX(activePointer) - initX);
else receiver.onMoveVertical(motionEvent.getX(activePointer) - initY);
}
break;
case ACTION_UP:
resolved = false;
receiver.onMovementStop();
break;
}
return true;
}
private Direction resolveDirection(float x, float y) {
float dx = x - initX;
float dy = y - initY;
float absDx = Math.abs(dx);
float absDy = Math.abs(dy);
if (absDx > absDy + 10) {
return Direction.HORIZONTAL;
} else if (absDy > absDx + 10) {
return Direction.VERTICAL;
}
return Direction.STILL;
}
public void setReceiver(GestureReceiver receiver) {
this.receiver = receiver;
}
private enum Direction {HORIZONTAL, VERTICAL, STILL;}
}
And i didn't start the Points class because i was not sure about the architecture.
I want this Connector to register all the listeners for the classes and wait for a change and inform the corresponding class of the change, like new point added or swipe started and finished or any other event in the app.
Chain of Responsibility might be what you are looking for.
It is a pattern to tie a series of 'processing objects' in a 'chain' that can handle 'command objects'.
I could see you making command objects that encapsulate the touch events and then get passed through several processors and finally get 'processed' by the 'processing objects' which handle input detection/output generation for that particular 'command object'.
I don't know if this is -ideal-, but it is potentially valid.
Other related patterns to look into might be:
https://en.wikipedia.org/wiki/Command_pattern
https://en.wikipedia.org/wiki/Observer_pattern
https://en.wikipedia.org/wiki/Bridge_pattern
Really what you're looking for here is an MVC-style architecture. Your application should (broadly speaking) be separated into 3 different areas:
the Model, which is completely divorced from your presentation or communication concerns. It provides an API for interaction and can be tested entirely independently with a simple framework such as JUnit.
the View, which is responsible for displaying the Model. It may be that a model can be displayed in different ways - in which case you get a single model and a few different views.
the Controller, which is responsible for making changes to the Model in response to user (or other) input.
The important thing is that the three sets of components are loosely-coupled and that responsibilities are clearly separated. All three should communicated via well defined interfaces (perhaps using the Observer, Command and ChainOfResponsibility patterns). In particular, the Model classes should have no direct knowledge of any of the View or Controller classes.
So, you might have some Model/View classes like this...
public interface ChartListener {
void notifyUpdate();
}
public interface Chart {
void newPoint(Point p);
Collection<Point> thePoints();
void addListener(ChartListener listener);
}
public class ChartModel implements Chart {
private final Collection<Point> points;
private final Collection<ChartListener> listeners;
public Collection<Point> thePoints() {
return Collections.unmodifiableCollection(points);
}
public void newPoint(Point p) {
thePoints.add(p);
listeners.stream().forEach(ChartListener::notifyUpdate);
}
public void addListener(ChartListener cl) {
listeners.append(cl);
}
}
public PieChartViewer implements ChartListener {
// All you colour management or appearance-related concerns is in this class.
private final Chart chart;
public PieChartView(Chart chart) {
this.chart = chart;
// set up all the visuals...
}
public void notifyUpdate() {
for (final Point p:chart.thePoints()) {
// draw a point somehow, lines, dots, etc,
}
}
}
Then you might have multiple different implementations of your View classes, utilising the ChartListener interface.
Your Swipe class seems like a Controller class, which would take a ChartModel implementation and then modify it in response to some input from the user.
I am a newbie in Android and Robolectric.
I am trying to simulate (as the topic indicates it) a drag event on a viewpager.
I have ever implemented this code and it runs on the emulator.
The matter is mostly: how can I unit test it?
Here is the unit test:
/** imports are skipped **/
#RunWith(RobolectricTestRunner.class)
#Config(manifest = "/src/main/AndroidManifest.xml")
public class TestImages {
private ImageActivity activity;
#InjectResource(R.drawable.ic_launcher)
private static Drawable image;
#Spy
private final PicturesModel picturesModel = spy(new PicturesModelImpl());
/**
* Last touched view
*/
private View lastTouchView;
/**
* Last touched X coordinate
*/
private float lastTouchX;
/**
* Last touched Y coordinate
*/
private float lastTouchY;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
final Module roboGuiceModule = RoboGuice.newDefaultRoboModule(Robolectric.application);
final Module pictureModule = Modules.override(roboGuiceModule).with(new PictureModule());
final Module testModule = Modules.override(pictureModule).with(new TestPictureModule(picturesModel));
RoboGuice.setBaseApplicationInjector(Robolectric.application, RoboGuice.DEFAULT_STAGE, testModule);
RoboInjector injector = RoboGuice.getInjector(Robolectric.application);
injector.injectMembersWithoutViews(this);
}
#Test
public void scroll_image() {
final Intent intent = new Intent(Robolectric.getShadowApplication().getApplicationContext(), ImageActivity.class);
final Album album = new Album(1, "album_1", image);
intent.putExtra("album", album);
intent.putExtra("position", 2);
intent.putExtra("imageId", 2L);
// Get the activity
activity = Robolectric.buildActivity(ImageActivity.class).withIntent(intent).create().get();
final Point point = new Point();
activity.getWindowManager().getDefaultDisplay().getSize(point);
// Get a spy viewer otherwise viewPager's width is always 0
final ViewPager viewPager = spy((ViewPager) activity.findViewById(R.id.viewPager));
viewPager.setVisibility(View.VISIBLE);
when(viewPager.getWidth()).thenReturn(point.x - 50);
// First item sent by viewPager before swipe
final int firstItem = viewPager.getCurrentItem();
// Swipe
drag(viewPager, 10F, 10F, point.x - 60F, 10F);
// Next item after swipe
final int secondItem = viewPager.getCurrentItem();
// Comparison
assertThat(firstItem).isEqualTo(2);
assertThat(secondItem).isEqualTo(3);
}
public void touchDown(View view, float x, float y) {
lastTouchX = x;
lastTouchY = y;
lastTouchView = view;
sendMotionEvent(view, MotionEvent.ACTION_DOWN, x, y);
}
public void touchMove(float x, float y) {
lastTouchX = x;
lastTouchY = y;
sendMotionEvent(lastTouchView, MotionEvent.ACTION_MOVE, x, y);
}
public void touchUp() {
sendMotionEvent(
lastTouchView, MotionEvent.ACTION_UP, lastTouchX, lastTouchY);
lastTouchView = null;
}
public void drag(View view, float xStart, float yStart,
float xEnd, float yEnd) {
touchDown(view, xStart, yStart);
touchMove(xEnd, yEnd);
touchUp();
}
private void sendMotionEvent(View view, int action, float x, float y) {
int[] screenOffset = new int[2];
view.getLocationOnScreen(screenOffset);
MotionEvent event = MotionEvent.obtain(100, 200, action,
x + screenOffset[0], y + screenOffset[1], 0);
shadowOf(event).setPointerIds(1, 2);
shadowOf(event).setPointerIndex(1);
view.onTouchEvent(event);
view.dispatchTouchEvent(event);
}
}
and the the activity:
public class ImageActivity extends RoboActivity {
#Inject
private PicturesModel picturesModel;
#InjectView(R.id.viewPager)
private ViewPager viewPager;
private PagerAdapter pagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.image);
final Bundle bundle = getIntent().getExtras();
if (bundle != null && !bundle.isEmpty()) {
final long id = (long) bundle.get("imageId");
final int position = (int) bundle.get("position");
final Picture picture = picturesModel.getPicture(id);
if (picture != null) {
pagerAdapter = new ImageAdapter(this, picturesModel.getAllPictures((Album) bundle.get("album")));
viewPager.setAdapter(pagerAdapter);
viewPager.setCurrentItem(position, true);
}
}
}
}
and this is the layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/viewPager" />
Does someone has an idea how to proceed or to tell me where is my mistake?
I think you what you are looking for is the Espresso library.
It simulates UI Events and let you check the state of the view once you threw the event and it is really easy to use. Just don't forget to switch animations off in the developers settings.
I've been working on the example from http://obviam.net/index.php/a-very-basic-the-game-loop-for-android/ In this I want to make few changes.
Speed.java
public class Speed {
public static final int DIRECTION_RIGHT = 1;
public static final int DIRECTION_LEFT = -1;
public static final int DIRECTION_UP = -1;
public static final int DIRECTION_DOWN = 1;
private float xv = 1; // velocity value on the X axis
private float yv = 1; // velocity value on the Y axis
private int xDirection = DIRECTION_RIGHT;
private int yDirection = DIRECTION_DOWN;
public Speed() {
this.xv = 1;
this.yv = 1;
}
public Speed(float xv, float yv) {
this.xv = xv;
this.yv = yv;
}
public float getXv() {
return xv;
}
public void setXv(float xv) {
this.xv = xv;
}
public float getYv() {
return yv;
}
public void setYv(float yv) {
this.yv = yv;
}
public int getxDirection() {
return xDirection;
}
public void setxDirection(int xDirection) {
this.xDirection = xDirection;
}
public int getyDirection() {
return yDirection;
}
public void setyDirection(int yDirection) {
this.yDirection = yDirection;
}
// changes the direction on the X axis
public void toggleXDirection() {
xDirection = xDirection * -1;
}
// changes the direction on the Y axis
public void toggleYDirection() {
yDirection = yDirection * -1;
}
}
Using this, the image moves in all directions. Now I just want to limit this movement from bottom to top. And the functionality for onclick is that, we can click and drag the image to required position. I want to replace that with just make the image to disappear or go to another activity. Please help me in making changes to this code. Thanks in advance.
if you have used SurfaceView then in onDraw(Canvas canvas) method the code is for moving image from bottom to top is something like this.
canvas.drawBitmap(bitmap,xPoint,yPoint,paint);
where bitmap is an image(Bitmap which you want to move),xPoint is the x coordinate,yPoint is the y coordinate and paint is a Paint which is also can be null.
and for bottom to top movement just update
yPoint = yPoint - 1;
in any thread before onDraw() call.
May this help you.
I have 10 picture on scene as sprites.And they are in an array.The pictures(sprites) are moving on scene by MoveModifier.
I want this: When I touch any picture,the picture which is I touched should be invisible.
my codes doesn't work because of 19. line(circles[i].setVisible(false);)
eclipse says me do i(variable) as final.I can't do that because i should change it's index of array.What can I do?
final int totalCircleNumber=10;
int circleNumber=0;
private Sprite[] circles = new Sprite[totalCircleNumber];
private Runnable mStartCircle = new Runnable() {
public void run() {
int i=circleNumber++;
Scene scene = Level1Activity.this.mEngine.getScene();
float startX = randomNumber.nextFloat()*(CAMERA_WIDTH);
float startY = -64.0f;
float finishX= randomNumber.nextFloat()*(CAMERA_WIDTH);
float finishY= CAMERA_HEIGHT+64.0f;
int j= randomNumber.nextInt(50);
circles[i] = new Sprite(startX, startY, textRegCircle[j]){
#Override
public boolean onAreaTouched(final TouchEvent pAreaTouchEvent,final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
if(pAreaTouchEvent.isActionDown())
{
circles[i].setVisible(false);
}
return true;
}
};
scene.registerTouchArea(circles[i]);
circles[i].registerEntityModifier(
(IEntityModifier) new SequenceEntityModifier (
new MoveModifier(velocityOfCircle, circles[i].getX(), finishX,
circles[i].getY(), finishY)));
scene.getLastChild().attachChild(circles[i]);
if (circleNumber < totalCircleNumber){
mHandler.postDelayed(mStartCircle,second);
}
}
};
replace:
circles[i].setVisible(false);
with
this.setVisible(false);