How to expand and collapse a layout above recyclerView when scrolling? - java

I have an app which have a recycler with product and anothe layout above with categories
I want to expand and collapse the categories when the recycler scroll like this video
I made a class that listens to scroll:
public abstract class MyRecyclerScroll extends RecyclerView.OnScrollListener {
final float MINIMUM = 200;
int scrollDist = 0;
boolean isVisible = true;
#Override
public void onScrolled(#NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (isVisible && scrollDist > MINIMUM) {
hide();
scrollDist = 0;
isVisible = false;
}
else if (!isVisible && scrollDist < -MINIMUM) {
show();
scrollDist = 0;
isVisible = true;
}
if ((isVisible && dy > 0) || (!isVisible && dy < 0)) {
scrollDist += dy;
}
}
public abstract void show();
public abstract void hide();
}
Then I used it on recycler.setOnScrollListener like this:
rec.setOnScrollListener(new MyRecyclerScroll() {
#Override
public void show() {
}
#Override
public void hide() {
}
});

Related

RecyclerView ItemTouchHelper BOTH Buttons on Swipe

Following this question
RecyclerView ItemTouchHelper Buttons on Swipe
(NOT THE SAME). I would like to add buttons on each side.
The official answer from that link is for ONE side only.
What I have tried:
public abstract class SwipeHelper extends ItemTouchHelper.SimpleCallback {
public static final int BUTTON_WIDTH = 125;
private RecyclerView recyclerView;
private List<UnderlayButton> buttons;
private GestureDetector gestureDetector;
private GestureDetector gestureDetector2;
private int swipedPos = -1;
private float swipeThreshold = 0.5f;
private Map<Integer, List<UnderlayButton>> buttonsBuffer;
private Queue<Integer> recoverQueue;
private GestureDetector.SimpleOnGestureListener gestureListener = new GestureDetector.SimpleOnGestureListener(){
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
for (UnderlayButton button : buttons){
if(button.onClick(e.getX(), e.getY()))
break;
}
return true;
}
};
private GestureDetector.SimpleOnGestureListener gestureListener2 = new GestureDetector.SimpleOnGestureListener(){
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
for (UnderlayButton button : buttons){
if(button.onClick2(e.getX(), e.getY()))
break;
}
return true;
}
};
private View.OnTouchListener onTouchListener = new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent e) {
if (swipedPos < 0) return false;
Point point = new Point((int) e.getRawX(), (int) e.getRawY());
RecyclerView.ViewHolder swipedViewHolder = recyclerView.findViewHolderForAdapterPosition(swipedPos);
View swipedItem = swipedViewHolder.itemView;
Rect rect = new Rect();
swipedItem.getGlobalVisibleRect(rect);
if (e.getAction() == MotionEvent.ACTION_DOWN || e.getAction() == MotionEvent.ACTION_UP ||e.getAction() == MotionEvent.ACTION_MOVE) {
if (rect.top < point.y && rect.bottom > point.y) {
gestureDetector.onTouchEvent(e);
gestureDetector2.onTouchEvent(e);
}
//else if(rect.top > point.y && rect.bottom < point.y){ }
else {
recoverQueue.add(swipedPos);
swipedPos = -1;
recoverSwipedItem();
}
}
return false;
}
};
public SwipeHelper(Context context, RecyclerView recyclerView) {
super(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT);
this.recyclerView = recyclerView;
this.buttons = new ArrayList<>();
this.gestureDetector = new GestureDetector(context, gestureListener);
this.gestureDetector2 = new GestureDetector(context, gestureListener2);
this.recyclerView.setOnTouchListener(onTouchListener);
buttonsBuffer = new HashMap<>();
recoverQueue = new LinkedList<Integer>(){
#Override
public boolean add(Integer o) {
if (contains(o))
return false;
else
return super.add(o);
}
};
attachSwipe();
}
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int pos = viewHolder.getAdapterPosition();
if (swipedPos != pos)
recoverQueue.add(swipedPos);
swipedPos = pos;
if (buttonsBuffer.containsKey(swipedPos))
buttons = buttonsBuffer.get(swipedPos);
else
buttons.clear();
buttonsBuffer.clear();
swipeThreshold = 0.5f * buttons.size() * BUTTON_WIDTH;
recoverSwipedItem();
}
#Override
public float getSwipeThreshold(RecyclerView.ViewHolder viewHolder) {
return swipeThreshold;
}
#Override
public float getSwipeEscapeVelocity(float defaultValue) {
return 0.1f * defaultValue;
}
#Override
public float getSwipeVelocityThreshold(float defaultValue) {
return 5.0f * defaultValue;
}
#Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
int pos = viewHolder.getAdapterPosition();
float translationX = dX;
View itemView = viewHolder.itemView;
if (pos < 0){
swipedPos = pos;
return;
}
if(actionState == ItemTouchHelper.ACTION_STATE_SWIPE){
if(dX < 0) {
List<UnderlayButton> buffer = new ArrayList<>();
if (!buttonsBuffer.containsKey(pos)){
instantiateUnderlayButton(viewHolder, buffer);
buttonsBuffer.put(pos, buffer);
}
else {
buffer = buttonsBuffer.get(pos);
}
translationX = dX * buffer.size() * BUTTON_WIDTH / itemView.getWidth();
drawButtons(c, itemView, buffer, pos, translationX);
}
if(dX > 0) {
List<UnderlayButton> buffer = new ArrayList<>();
if (!buttonsBuffer.containsKey(pos)){
instantiateUnderlayButton(viewHolder, buffer);
buttonsBuffer.put(pos, buffer);
}
else {
buffer = buttonsBuffer.get(pos);
}
translationX = dX * buffer.size() * BUTTON_WIDTH / itemView.getWidth();
drawButtons(c, itemView, buffer, pos, translationX);
}
}
super.onChildDraw(c, recyclerView, viewHolder, translationX, dY, actionState, isCurrentlyActive);
}
private synchronized void recoverSwipedItem(){
while (!recoverQueue.isEmpty()){
int pos = recoverQueue.poll();
if (pos > -1) {
recyclerView.getAdapter().notifyItemChanged(pos);
}
}
}
private void drawButtons(Canvas c, View itemView, List<UnderlayButton> buffer, int pos, float dX) {
float right = itemView.getRight();
float left = itemView.getLeft();
float dButtonWidth = (-1) * dX / buffer.size();
for (UnderlayButton button : buffer) {
if (dX < 0) {
left = right - dButtonWidth;
button.onDraw(
c,
new RectF(
left,
itemView.getTop(),
right,
itemView.getBottom()
),
pos, dX
);
right = left;
} else if (dX > 0) {
right = left - dButtonWidth;
button.onDraw(c,
new RectF(
right,
itemView.getTop(),
left,
itemView.getBottom()
), pos, dX
);
left = right;
}
}
}
public void attachSwipe(){
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(this);
itemTouchHelper.attachToRecyclerView(recyclerView);
}
public abstract void instantiateUnderlayButton(RecyclerView.ViewHolder viewHolder, List<UnderlayButton> underlayButtons);
public static class UnderlayButton {
private String text;
private int imageResId;
private int color;
private UnderlayButtonClickListener clickListener;
private String text2;
private int imageResId2;
private int color2;
private UnderlayButtonClickListener2 clickListener2;
private RectF clickRegion;
private RectF clickRegion2;
private int pos;
public UnderlayButton(String text, int imageResId, int color, UnderlayButtonClickListener clickListener, String text2, int imageResId2, int color2, UnderlayButtonClickListener2 clickListener2) {
this.text = text;
this.imageResId = imageResId;
this.color = color;
this.clickListener = clickListener;
this.text2 = text2;
this.imageResId2 = imageResId2;
this.color2 = color2;
this.clickListener2 = clickListener2;
}
public boolean onClick(float x, float y){
if (clickRegion != null && clickRegion.contains(x, y)){
clickListener.onClick(pos);
return true;
}
return false;
}
public boolean onClick2(float x, float y){
if (clickRegion2 != null && clickRegion2.contains(x, y)){
clickListener2.onClick(pos);
return true;
}
return false;
}
public void onDraw(Canvas c, RectF rect, int pos, float dX) {
Paint p = new Paint();
// Draw background
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (dX < 0) {
//Boton derecho
c.drawRect(rect, p);
p.setColor(color);
}
else{
//Boton Izquierdo
p.setColor(color2);
c.drawRect(rect, p);
}
clickRegion = rect;
clickRegion2 = rect;
this.pos = pos;
}
}
}
public interface UnderlayButtonClickListener {
void onClick(int pos);
}
public interface UnderlayButtonClickListener2 {
void onClick(int pos);
}}
I tried adding more parameters to the "UnderlayButton" class because before I tried to use the two classes separately but it was throwing me problems with the OnClickListener.
So the best way I found was to add extra parameters in the "UnderlayButton" class. Still, it doesn't work for me.
Could someone help me please.

How to draw circle according to point array list?

I am creating a test game where a circle will move to a selected position from the point array list when touched. However, it seems that it cannot move to the next position of points when clicked. Can u help me find where is the problem is and what solution I can use?
public class EyeTestActivity extends AppCompatActivity {
private GestureDetectorCompat mDetector;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new TestView(this));
// get the gesture detector
mDetector = new GestureDetectorCompat(EyeTestActivity.this, new SwipeGestureDetector());
}
public boolean onTouchEvent(MotionEvent motionEvent) {
this.mDetector.onTouchEvent(motionEvent);
return super.onTouchEvent(motionEvent);
}
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
super.dispatchTouchEvent(ev);
return mDetector.onTouchEvent(ev);
}
public class TestView extends View {
public ArrayList<Point> pointlist;
Paint paint;
public TestView(Context context) {
super(context);
init();
setFocusable(true);
setFocusableInTouchMode(true);
createPointList();
}
public void init() {
paint = new Paint();
paint.setColor(Color.WHITE);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
}
public void createPointList() {
pointlist = new ArrayList<>();
for (int i = 1; i <= 5; i++) {
float a = 100 * i;
float b = 100 * i;
for (int j = 1; j <= 24; j++) {
float x = (float) (a * Math.sin(Math.toRadians(15 * j)));
float y = (float) (b * Math.cos(Math.toRadians(15 * j)));
for (int k = 0; k < 120; k++) {
pointlist.add(new Point(x, y));
//Add the x and y coordinates to the Point
}
}
}
}
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
paint.setStyle(Paint.Style.FILL);
canvas.drawColor(Color.BLACK);
Point point2 = pointlist.get(z);
canvas.drawCircle(point2.getX() + canvas.getWidth() / 2, point2.getY() + canvas.getHeight()/ 2, 15, paint);
}
}
int z = 0;
public class SwipeGestureDetector implements GestureDetector.OnGestureListener {
#Override
public boolean onDown(MotionEvent e) {
return true;
}
#Override
public void onShowPress(MotionEvent e) {
}
#Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
if (e1.getAction() == MotionEvent.ACTION_MOVE) {
z++;
if (z > 120) {
z = 0;
}
}
return true;
}
#Override
public void onLongPress(MotionEvent e) {
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if(e1 == null || e2 == null)
return false;
if(e1.getPointerCount() > 1 || e2.getPointerCount() > 1)
return false;
else {
try {
float diffX = e2.getX() - e1.getX();
float diffY = e2.getY() - e1.getY();
if(Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > 100 && Math.abs(velocityX) > 1000) {
if ((diffX > 0) || (diffX < 0)) {
return false;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
}
}
I expect the next circle to be drawn when printed.
First of all, you should have a reference to your TestView layout.
public class EyeTestActivity extends AppCompatActivity {
private GestureDetectorCompat mDetector;
private TestView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
tv = new TestView(this);
setContentView(tv);
// get the gesture detector
mDetector = new GestureDetectorCompat(EyeTestActivity.this, new SwipeGestureDetector());
}
Then, in your onScroll event, you should test e2 instead of e1
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
if (e2.getAction() == MotionEvent.ACTION_MOVE) {
z++;
if (z >= 120) { // zero based arraylist, so, >= 120
z = 0;
}
tv.invalidate; // this to redraw the point
}
return true;
}
I think your createPointList is not doing what you want.
You are creating 120 times the same point! Total 120 * 5 * 24 = 14.400 points !
It should be
for (int i = 1; i <= 5; i++) {
float a = 100 * i;
float b = 100 * i;
for (int j = 1; j <= 24; j++) {
float x = (float) (a * Math.sin(Math.toRadians(15 * j)));
float y = (float) (b * Math.cos(Math.toRadians(15 * j)));
pointlist.add(new Point((int)x, (int)y));
}
}

Android, java, view.setOnTouchListener

I had a recyclerview with an adapter and everything was cool. I added view.setOnTouchListener so that I could scroll this recyclerview along with animation and other elements on 1 screen from left to right. But after that, scrolling up and down broke in recyclerview, and onclicklistener on the elements inside it stopped working. What to do and how to fix this conflict?
At the moment I can put return false in the public boolean onTouch (View v, MotionEvent event) method; instead of return gestureDetector.onTouchEvent (event); and get a working scrolling up and down back, but left-right stops working. I can do simultaneous scrolling as in ios, when scrolling of tablecloths and collections did not break when adding the svayp to the left-right.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
view.setOnTouchListener(new OnSwipeTouchListener(MainActivity.this) {
public void onSwipeRight() {
choseold = chosenow;
chosenow = chosenow - 1;
if (chosenow <= 0) {
chosenow = 5;
choseold = 6;
}
swipe();
}
public void onSwipeLeft() {
choseold = chosenow;
chosenow = chosenow + 1;
if (chosenow >= 6) {
chosenow = 1;
choseold = 0;
}
swipe();
}
});
view.setFocusableInTouchMode(true);
MyAdapterlang = new MyAdapterLang(MainActivity.this, yaziki1, yaziki2, flagi);
RVlang.setAdapter(MyAdapterlang);
mLayoutManager = new LinearLayoutManager(this);
RV1.setLayoutManager(mLayoutManager);
MyAdapter = new MyAdapterApps(MainActivity.this, childs, childs2);
RV1.setAdapter(MyAdapter);
}
}
class OnSwipeTouchListener implements View.OnTouchListener {
private final GestureDetector gestureDetector;
public OnSwipeTouchListener (Context ctx){
gestureDetector = new GestureDetector(ctx, new GestureListener());
}
#Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
//return false;
}
/*public boolean onTouch(final View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
y1 = event.getY();
break;
case MotionEvent.ACTION_MOVE:
y2 = event.getY();
float deltaY = y2 - y1;
if (Math.abs(deltaY) > MIN_DISTANCE) {
return false;
} else {
return gestureDetector.onTouchEvent(event);
}
}
return gestureDetector.onTouchEvent(event);
}
private float y1, y2;
private static final int MIN_DISTANCE = 50;*/
private final class GestureListener extends GestureDetector.SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
#Override
public boolean onDown(MotionEvent e) {
return true;
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
onSwipeRight();
} else {
onSwipeLeft();
}
return true;
}
}
} catch (Exception exception) {
exception.printStackTrace();
}
return false;
}
}
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
}
Here in ios, for example, is very simple and does not break the scrolling of collections:
- (void)viewDidLoad {
UISwipeGestureRecognizer * swipeleft=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(swipeleft:)];
swipeleft.direction=UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:swipeleft];
UISwipeGestureRecognizer * swiperight=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(swiperight:)];
swiperight.direction=UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:swiperight];
}
-(void)swipeleft:(UISwipeGestureRecognizer*)gestureRecognizer
{
if (self.currentnew <= 3) {
self.whatpress = 1;
[self.buttonnew sendActionsForControlEvents:UIControlEventTouchUpInside];
}
}
-(void)swiperight:(UISwipeGestureRecognizer*)gestureRecognizer
{
if ((self.currentnew >= 1) && (self.currentnew <= 3)) {
self.whatpress = 2;
[self.buttonnew sendActionsForControlEvents:UIControlEventTouchUpInside];
}
}
Here is a video:
https://2ch.hk/pr/src/1314926/15464190246250.mp4 https://2ch.hk/pr/src/1314926/15464193253190.mp4
If you only want to hook into default touch handling implementation you must return false here
#Override
public boolean onTouch(View v, MotionEvent event) {
gestureDetector.onTouchEvent(event);//Idk if it is needed or not - out of scope
return false;
}
Otherwise touch event will be considered as consumed and wont be propagated to other handlers (that handles scrolling, clicking etc. - all that stuff that stops working for you)

android - animate on swipe

In my new program I need objects that can be swiped to the side. I already have my animation, which is working and I tried to detect the swiping of the user in another class. The problem I have is that I don't know how to connect them. When the swipe gesture is correctly recognized a specific animation should start.
My AnimatedViewClass:
private Runnable r = new Runnable() {
#Override
public void run() {
if(continueAnimation) {
invalidate();
}
}
};
protected void onDraw(Canvas c) {
if (x<0) {
x = this.getWidth()/2-100;
y = this.getHeight()/2-100;
}
else {
x += xVelocity;
if ((x > this.getWidth() - ball.getBitmap().getWidth()) || (x < 0)) {
boolean continueAnimation = false;
}
}
c.drawBitmap(ball.getBitmap(), x, y, null);
if(continueAnimation)
{
h.postDelayed(r, FRAME_RATE);
}
else {
x = this.getWidth()-ball.getBitmap().getWidth();
}
}
My SwipeTouchListener:
public class OnSwipeTouchListener implements OnTouchListener {
private final GestureDetector gestureDetector;
public OnSwipeTouchListener (Context ctx){
gestureDetector = new GestureDetector(ctx, new GestureListener());
}
#Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
private final class GestureListener extends SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
#Override
public boolean onDown(MotionEvent e) {
return true;
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
onSwipeRight();
} else {
onSwipeLeft();
}
}
result = true;
}
else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
onSwipeBottom();
} else {
onSwipeTop();
}
}
result = true;
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
}
}
You can add GestureDetector to your view class just like this, and replace your code inside onFling()
public class AnimatedViewClass extends View {
GestureDetector gestureDetector;
public AnimatedViewClass(Context context) {
super(context);
gestureDetector = new GestureDetector(getContext(), new GestureDetectorListener());
}
#Override
public boolean onTouchEvent(MotionEvent event) {
gestureDetector.onTouchEvent(event);
return super.onTouchEvent(event);
}
private void onSwipeRight(){
// swipe right detected
// do stuff
invalidate();
}
private void onSwipeLeft(){
// swipe left detected
// do stuff
invalidate();
}
private class GestureDetectorListener extends
GestureDetector.SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
// onSwipeRight()
// onSwipeLeft()
return super.onFling(e1, e2, velocityX, velocityY);
}
#Override
public boolean onDown(MotionEvent e) {
return super.onDown(e);
}
}
private Runnable r = new Runnable() {
#Override
public void run() {
if(continueAnimation) {
invalidate();
}
}
};
protected void onDraw(Canvas c) {
if (x < 0) {
x = this.getWidth() / 2 - 100;
y = this.getHeight() / 2 - 100;
} else {
x += xVelocity;
if ((x > this.getWidth() - ball.getBitmap().getWidth()) || (x < 0)) {
boolean continueAnimation = false;
}
}
c.drawBitmap(ball.getBitmap(), x, y, null);
if (continueAnimation) {
h.postDelayed(r, FRAME_RATE);
} else {
x = this.getWidth() - ball.getBitmap().getWidth();
}
}
}

ImageView not initialized

I'm testing out my system for hitboxes for a game i'm making. The problem is that i get the following error in my ball class:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.Window.findViewById(int)' on a null object reference
It happens in the first line in the constructor method in the ball class.
Does anyone know if i'm doing anything wrong?
main class:
package xander.mazetestapp;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements SensorEventListener {
private TextView text;
private SensorManager sManager;
private int a = 300; //x position
private int b = 300; //y position
int x = 0;
int y = 0;
ball playingBall;
wall mazeWall;
float show = 1;
float hide = 0;
boolean allowedMovement[] = {true, true, true, true};
int maxX = 0;
int maxY = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.info);
sManager = (SensorManager) getSystemService(SENSOR_SERVICE);
playingBall = new ball();
mazeWall = new wall(hide, R.id.wall1);
}
//when this Activity starts
#Override
protected void onResume() {
super.onResume();
/*register the sensor listener to listen to the gyroscope sensor, use the
callbacks defined in this class, and gather the sensor information as quick
as possible*/
sManager.registerListener(this, sManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_FASTEST);
}
//When this Activity isn't visible anymore
#Override
protected void onStop() {
//unregister the sensor listener
sManager.unregisterListener(this);
super.onStop();
}
#Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
//Do nothing.
}
public void limitMovement(ball ball, wall wall) {
float wy = (ball.getWidth() + wall.getWidth()) * (ball.getCenterY() - wall.getCenterY());
float hx = (ball.getHeight() + wall.getHeight()) * (ball.getCenterX() - wall.getCenterX());
if (wy > hx) {
if (wy > -hx) {//top
allowedMovement[1] = false;
} else {//left
allowedMovement[2] = false;
}
} else {
if (wy > -hx) {//right
allowedMovement[3] = false;
} else {//bottom
allowedMovement[0] = false;
}
}
}
public boolean intersect(ball ball, wall wall) {
//top left corner of the ball
if (ball.getTopLeftX() >= wall.getTopLeftX() && ball.getTopLeftX() <= wall.getTopRightX()) {
if (ball.getTopLeftY() >= wall.getTopLeftY() && ball.getTopLeftY() <= wall.getBottomLeftY()) {
limitMovement(ball, wall);
return true;
}
}
//top rigth corner of the ball
if (ball.getTopRightX() >= wall.getTopLeftX() && ball.getTopRightX() <= wall.getTopRightX()) {
if (ball.getTopRightY() >= wall.getTopLeftY() && ball.getTopRightY() <= wall.getBottomLeftY()) {
limitMovement(ball, wall);
return true;
}
}
//bottom left corner of the ball
if (ball.getBottomLeftX() >= wall.getBottomLeftX() && ball.getBottomLeftX() <= wall.getBottomRightX()) {
if (ball.getBottomLeftY() >= wall.getTopLeftY() && ball.getBottomLeftY() <= wall.getBottomLeftY()) {
limitMovement(ball, wall);
return true;
}
}
//bottom rigth corner of the ball
if (ball.getBottomRightX() >= wall.getBottomLeftX() && ball.getBottomRightX() <= wall.getBottomRightX()) {
if (ball.getBottomRightY() >= wall.getTopLeftY() && ball.getBottomRightY() <= wall.getBottomLeftY()) {
limitMovement(ball, wall);
return true;
}
}
return false;
}
public void move(int x, int y) {
RelativeLayout.LayoutParams alp = playingBall.getLayoutParams();
int maxMovementX = Math.abs(x);
int maxMovenentY = Math.abs(y);
int stepsTakenX = 0;
int stepsTakenY = 0;
while (maxMovementX > stepsTakenX || maxMovenentY > stepsTakenY) {
//up 0, down 1, right 3, left 2
if (stepsTakenX < maxMovementX) {
stepsTakenX = stepsTakenX + 1;
if (x > 0 && allowedMovement[3] == true) {//right
playingBall.setCenterX(playingBall.getCenterX() - 1);
a = a - 1;
}
if (x < 0 && allowedMovement[2] == true) {//left
playingBall.setCenterX(playingBall.getCenterX() + 1);
a = a + 1;
}
}
if (stepsTakenY < maxMovenentY) {
stepsTakenY = stepsTakenY + 1;
if (y > 0 && allowedMovement[1] == true) {//down
playingBall.setCenterY(playingBall.getCenterY() - 1);
b = b - 1;
}
if (y < 0 && allowedMovement[0] == true) {//up
playingBall.setCenterY(playingBall.getCenterY() + 1);
b = b + 1;
}
}
}
alp.leftMargin = a;
alp.topMargin = b;
playingBall.setLayoutParams(alp);
}
#Override
public void onSensorChanged(SensorEvent event) {
//if sensor is unreliable, return void
if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) {
return;
}
//else it will output the Roll, Pitch and Yawn values
x = Math.round(event.values[2]) / 3;
y = Math.round(event.values[1]) / 3;
if (x > 15) {
x = 15;
}
if (x < -15) {
x = -15;
}
if (y > 15) {
y = 15;
}
if (y < -15) {
y = -15;
}
//kleinere x is naar links
//kleinere y is naar boven
//balk1 is boven
//balk2 is onder
//balk3 is links
//balk 4 is rechts
move(x, y);
text.setText("Width: " + playingBall.getWidth() +
" Height: " + playingBall.getHeight() +
" B x: " + playingBall.getCenterX() +
" B y: " + playingBall.getCenterY() +
" W x: " + mazeWall.getCenterX() +
" W y: " + mazeWall.getCenterY() +
" wall LB x: " + mazeWall.getTopLeftX() +
" wall LB y: " + mazeWall.getTopLeftY() +
"Width: " + mazeWall.getWidth() +
" Height: " + mazeWall.getHeight()
);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
ball class:
package xander.mazetestapp;
import android.app.Activity;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.RelativeLayout;
public class ball extends AppCompatActivity {
private int centerX;
private int centerY;
private int topLeftX;
private int topRightX;
private int bottomLeftX;
private int bottomRightX;
private int topLeftY;
private int topRightY;
private int bottomLeftY;
private int bottomRightY;
private int width;
private int height;
public ImageView ballImage;
public ball(){
ballImage = (ImageView) findViewById(R.id.ball);
centerX =(int) ballImage.getX();
centerY = (int) ballImage.getY();
width = ballImage.getWidth();
height = ballImage.getHeight();
setCorners();
}
private void setCorners() {
topLeftX=(centerX-(width/2));
topLeftY=(centerY-(height/2));
topRightX=(centerX+(width/2));
topRightY=(centerY-(height/2));
bottomRightX=(centerX+(width/2));
bottomRightY=(centerY+(height/2));
bottomLeftX=(centerX-(width/2));
bottomLeftY=(centerY+(height/2));
}
public int getWidth(){
return width;
}
public int getHeight(){
return height;
}
public int getCenterX(){
return centerX;
}
public int getCenterY(){
return centerY;
}
public int getTopLeftX(){
return topLeftX;
}
public int getTopRightX(){
return topRightX;
}
public int getBottomLeftX(){
return bottomLeftX;
}
public int getBottomRightX(){return bottomRightX;}
public int getTopLeftY(){
return topLeftY;
}
public int getTopRightY(){
return topRightY;
}
public int getBottomLeftY(){
return bottomLeftY;
}
public int getBottomRightY(){
return bottomRightY;
}
public void setCenterX(int x){
centerX=x;
}
public void setCenterY(int y){
centerY=y;
}
public RelativeLayout.LayoutParams getLayoutParams(){
return (RelativeLayout.LayoutParams) ballImage.getLayoutParams();
}
public void setLayoutParams(RelativeLayout.LayoutParams alp){
ballImage.setLayoutParams(alp);
}
I guess Hardik is right ball class is an activity as you have used extends appCompatActivity. So you have to initialize the image view in onCreate method.
For any activity initialisation takes place after onCreate() you need to get the ImageView reference in the onCreate() and make sure you set the layout in setContentView() and then get the ImageView reference
Your ball class is not actually an activity. It is a simple class. You do not need to extends AppCompatActivity. Just make the constructor of ball class with the parameter as a context and then using that context you can get imageview.
i.e.
Changes in ball.java are below:
remove "extends AppCompatActivity" and make it simple class.
public ball(Context context){
ballImage = (ImageView) context.findViewById(R.id.ball);
centerX =(int) ballImage.getX();
centerY = (int) ballImage.getY();
width = ballImage.getWidth();
height = ballImage.getHeight();
setCorners();
}
Changes in main.java are below:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.info);
sManager = (SensorManager) getSystemService(SENSOR_SERVICE);
playingBall = new ball(this); // Here we pass the context of the current activity
mazeWall = new wall(hide, R.id.wall1);
}

Categories

Resources