I'm trying to create a simple app with a ball moving around reflecting off the screen edges.
I've found out how to create my ball. However i'm not able to move it around.
Here's my code till now.
protected void onCreate(Bundle savedInstanceState) {
initial_x=100;
initial_y=100;
speed_x=1;
speed_y=1;
x=initial_x;
y=initial_y;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
draw();
}
private void draw() {
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
height = displaymetrics.heightPixels;
width = displaymetrics.widthPixels;
Log.d("dimensions",String.valueOf(width));
Log.d("dimensions",String.valueOf(height));
Bitmap bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
g = new Canvas(bitmap);
g.drawColor(Color.WHITE);
paint = new Paint();
paint.setColor(Color.RED);
g.drawCircle(50,50, 20, paint); //Put your values
// In order to display this image, we need to create a new ImageView that we can display.
ImageView imageView = new ImageView(this);
// Set this ImageView's bitmap to ours
imageView.setImageBitmap(bitmap);
// Create a simple layout and add imageview to it.
RelativeLayout layout = new RelativeLayout(this);
RelativeLayout.LayoutParams params = new
RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.CENTER_IN_PARENT);
layout.addView(imageView, params);
layout.setBackgroundColor(Color.BLACK);
// Show layout in activity.
setContentView(layout);
layout.setOnClickListener(l);
}
I've set an onclick listener to basically be able to move the ball when i touch the screen. How do I make this a continuous process?
Edit:
I changed the onclicklistener to an ontouchlistener to keep the ball moving while i touch the screen but it still works like an onclick listener. here is the code
OnTouchListener l = new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
g.drawColor(Color.WHITE);
x+=speed_x;
y+=speed_y;
g.drawCircle(x, y, 20, paint);
if(x==0)
speed_x=-1;
if(x==height)
speed_x=1;
if(y==0)
speed_y=-1;
if(y==width)
speed_y=1;
v.invalidate();
break;
}
return false;
}
};
Use a TimerTask to periodically update the position continuously. Probably 10 to 30 times a second should suffice.
Put your drawing and position update logic in the run() method of TimerTask since creating another thread won't work. (Drawing must occur on GUI thread).
Hope this helps.
Edit:
TimerTask myTimerTask = new TimerTask() {
#Override
public void run() {
// Update logic here
runOnUiThread(new Runnable() {
#Override
public void run() {
// Drawing logic here
}
});
}
}
Timer timer = new Timer();
timer.schedule(myTimerTask, 50, 50);
Related
Here the ImageView is displaying only at one position, after closing the activity the next time the activity is opened the ImageView will be on another position... I want to display the ImageView randomly at diff position on the same activity itself. The image view should appear on one point suddenly the next second ImageView should disappear from that position and appear on the next position. How can i do it?
public class page2 extends ActionBarActivity {
ImageView b2;
int count = 0;
Handler handler = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_page2);
Intent c = getIntent();
String name = c.getStringExtra("t");
Toast.makeText(getApplicationContext(), name, Toast.LENGTH_SHORT).show();
b2 = (ImageView) findViewById(R.id.redball);
AbsoluteLayout.LayoutParams absParams =
(AbsoluteLayout.LayoutParams)b2.getLayoutParams();
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int width = displaymetrics.widthPixels;
int height = displaymetrics.heightPixels;
Random r = new Random();
absParams.x = r.nextInt(width ) ;
absParams.y = r.nextInt(height );
b2.setLayoutParams(absParams);
Animation animation = AnimationUtils.loadAnimation(page2.this, R.anim.fade);
// Animation animation1 = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.activity_move);
b2.startAnimation(animation);
// b2.startAnimation(animation1);
b2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
count = count + 1;
}
});
handler = new Handler();
final Runnable t = new Runnable() {
public void run() {
Intent d = new Intent(getApplicationContext(), Page3.class);
d.putExtra("count", count);
d.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(d);
}
};
handler.postDelayed(t, 4000);
}
#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_page2, menu);
return true;
}
Don't use AbsoluteLayout, Why not use a custom view draw it?
You can achieve this by using Imageview within FrameLayout. Just change the layoutParams of the image to change its position.
As I understand it, you want that each time the activity is opened, so f you dont want to actually view to the user that the ImageView moves, why are you using Animation? You may just dynamically add the ImageView to the activity each time, and each time assign it different Margin attributes.
LinearLayout layout = (LinearLayout) view.findViewById(R.id.linear);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);
params.setMargins(0, 0, 10, 0); //substitute parameters for left, top, right, bottom
ImageView iv = new ImageView(getActivity());
iv.setLayoutParams(params);
iv.setImageResource(R.drawable.yourimage);
layout.addView(iv);
for calucation
ContainerHeight = blinkerContainer.getHeight(); // total height of screen
ContainerWidth = blinkerContainer.getWidth(); //total width
blinkerHeight = blinkView.getHeight();
blinkerWidth = blinkView.getWidth();
minTopMargin = 30;
minLeftMargin = 30;
maxTopMargin = ContainerHeight - blinkerHeight - 30;
maxLeftMargin = ContainerWidth - blinkerWidth - 30;
for positioning
LinearLayout.LayoutParams params = (android.widget.LinearLayout.LayoutParams) blinkView
.getLayoutParams();
params.leftMargin = minLeftMargin
+ new Random().nextInt(maxLeftMargin - minLeftMargin);
params.topMargin = minTopMargin
+ new Random().nextInt(maxTopMargin - minTopMargin);
and you can use AlaramManager for Scheduling
Your solution is almost correct. Unfortunately, it looks like you're restarting the activity from your timer. Instead, you should just trigger the redraw.
This question has a couple of solutions on how to create a recurring timer. The solution with runOnUiThread() should allow you to execute the randomisation and re-displaying of the ImageView.
I have an imageview, and after i add image (a marker) on this imageview.
At the end, i want to create a bitmap, included the new marker.
But if i try to create a bitmap from relative layout, i create an image without new marker! Why?
imageview= (ImageView)findViewById(R.id.image);
//insert a marker on my imageview
final RelativeLayout rr = (RelativeLayout) findViewById(R.id.relative);
rr.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
int x = (int) event.getX() ;
int y = (int) event.getY();
RelativeLayout.LayoutParams lp =new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);; //Assuming you use a RelativeLayout
ImageView iv=new ImageView(getApplicationContext());
lp.setMargins(x,y,0,0);
iv.setLayoutParams(lp);
iv.setImageDrawable(getResources().getDrawable(R.drawable.marker));
((ViewGroup)v).addView(iv);
//create a bitmap from relative layout but the new bitmap is without marker
Bitmap b1 = Bitmap.createBitmap(rr.getWidth(), rr.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b1);
((ViewGroup)v).draw(c);
}
return false;
}
It happens because adding marker dynamically to the layout, to add dynamic views it has some delay. Thats the reason creating bitmap without marker. On second touch with singe marker bitmap will be created. The solution is save bitmap after some delay.
Solution is here:
private Handler handler = new Handler(); //handler object in global
rr.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
int x = (int) event.getX() ;
int y = (int) event.getY();
RelativeLayout.LayoutParams lp =new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);; //Assuming you use a RelativeLayout
ImageView iv=new ImageView(getApplicationContext());
lp.setMargins(x,y,0,0);
iv.setLayoutParams(lp);
iv.setImageDrawable(getResources().getDrawable(R.drawable.marker));
((ViewGroup)v).addView(iv);
//run handler after 1000 milli seconds i.e 1 sec
handler.postDelayed(runnable, 1000);
}
return false;
}
private Runnable runnable = new Runnable() {
#Override
public void run() {
//wrote your block of code here
//create a bitmap from relative layout but the new bitmap is without marker
Bitmap b1 = Bitmap.createBitmap(rr.getWidth(), rr.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b1);
((ViewGroup)v).draw(c);
}
};
Look here How to Save Bitmap as image in SD card
As a example,have to draw a layout of images.
I inflated an ImageView into a layout. When I swipe on the screen I need to change the color of the each circle to green. How should I do it. I tried with gesture detector, but I can't get what I need.
and this is my code.. I create this view by inflating an image view..
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().addFlags(1024);
setContentView(R.layout.test);
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
height = displaymetrics.heightPixels;
width = displaymetrics.widthPixels;
count = width/30;
totalCircles = count * (height/30);
horizontalSpace = width%30;
verticalSpace = height%30;
mRelativeLayout = (RelativeLayout)findViewById(R.id.fl);
mRelativeLayout.setPadding(horizontalSpace/2, verticalSpace/2, horizontalSpace/2, verticalSpace/2);
for(int i=1;i<totalCircles+1;i++){
myButton = new ImageView(this);
myButton.setId(i);
myButton.setImageResource(R.drawable.circle_grey);
LayoutParams lp = new LayoutParams(0,0);
if(i%count != 1){
lp.addRule(RelativeLayout.RIGHT_OF, imgViews.get(i-2).getId());
if(imView != null){
lp.addRule(RelativeLayout.BELOW, imView.getId());
}
if(i%count == 0){
imView = myButton;
}
}else{
if(imView != null){
lp.addRule(RelativeLayout.BELOW, imView.getId());
}
}
mRelativeLayout.addView(myButton,lp);
myButton.getLayoutParams().width = 30;
myButton.getLayoutParams().height = 30;
imgViews.add(myButton);
myButton.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
System.out.println("Inside touch listener");
ImageView imV = (ImageView)v;
imV.setImageResource(R.drawable.circle_green);
}
return false;
}
});
}
}
Jack K Fouani's answer is partially correct. Instead of imagView.onTouch you need to use gridview.onTouch.
Please check this sample.
gv.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
float currentXPosition = event.getX();
float currentYPosition = event.getY();
int position = gv.pointToPosition((int)currentXPosition, (int) currentYPosition);
//using the position obtained you can change the imageview color.
}
return true;
}
});
Instead of inflating one ImageView. You should fill a GridView where every GridCell contains a circle image. Now
set the OnTouchEvent of those Gridcells to change the ImageView within the GridCell.
my advice is to use GrideView with adapter , inside the adapter you will have position for each imagView the position allow you to check if image is touched or not depending on that you can change ImageView color to white or green
I am creating a boardgame for Android and I have an animation that I wish to do when a specific motion event occurs.
I have a Boardview class which draws on a surfaceview with bitmaps and this shows the user the board.
When a motion event happens, this code executes
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Intent animate = new Intent(Tempboardview.this, Moving.class);
animate.putExtra("xOld", oldStones.get(i).getx());
animate.putExtra("yOld", oldStones.get(i).gety());
animate.putExtra("xNew", newStones.get(i).getx());
animate.putExtra("yNew", newStones.get(i).gety());
animate.putExtra("color", 0);
startActivity(animate);
}
}
where newStones and oldStones are simply ArrayList objects and gety() and getx() return doubles.
This is my Moving class
public class Moving extends Activity {
private static final String TAG = "Animation";
double xOld = 0, yOld = 0, xNew = 0, yNew = 0, color = 0;
/** Called when the activity is first created. */#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
LayoutInflater inflater = getLayoutInflater();
addContentView(inflater.inflate(R.layout.move, null),
new ViewGroup.LayoutParams(800, 480));
final ImageView image = (ImageView) findViewById(R.id.stoneimager);
image.setVisibility(View.GONE);
image.bringToFront();
Bundle extras = getIntent().getExtras();
if (extras != null) {
xOld = extras.getDouble("xOld");
yOld = extras.getDouble("yOld");
xNew = extras.getDouble("xNew");
yNew = extras.getDouble("yNew");
color = extras.getDouble("color");
}
Animation animate = new TranslateAnimation((float) xOld, (float) xNew, (float) yOld, (float) yNew);
animate.setDuration(1000);
animate.setStartOffset(0);
animate.setInterpolator(new LinearInterpolator());
animate.setRepeatCount(0);
animate.setFillAfter(true);
animate.setZAdjustment(Animation.ZORDER_TOP);
Animation.AnimationListener listener = new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
Log.d("boardtag", "animation started");
image.setVisibility(View.VISIBLE);
image.bringToFront();
}
#Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animation animation) {
// TODO Auto-generated method stub
image.setVisibility(View.GONE);
finish();
}
};
animate.setAnimationListener(listener);
Log.d("boardtag", "animation started");
image.startAnimation(animate);
}
}
The problem is the animation is not able to take place while the board is still displayed.
I have used the android manifest to change the theme of .Moving to Transparent, but this did not work.
Any advice would be appreciated.
This is probably going to come off more harsh than I intend, but I think you are completely abusing the Intent/Activity features. You need to seriously consider redesigning your UI layer to be more closely coupled with the active Activity.
What you have above should be painfully slow since motion events are common and Activity creation and Intent dispatching is expensive (relatively). What you need is a single main "game" Activity that is tightly coupled with a SurfaceView (probably OpenGL since this has animations and it's a game). This activity would take user input (UI events) and translate them into drawing commands for your surface view directly.
I have a FrameLayout containing a subclassed SurfaceView and an ImageView. I want to do a TranslateAnimation on the ImageView. The only way I can make it work is to add a vacuous View to the FrameLayout. Otherwise, the ImageView gets clipped (to the bounds of the ImageView's position at the start of the animation) during the animation.
I'm curious as to why the empty sibling View allows the ImageView to animate correctly. The line that makes it work is marked with a comment in the code below.
public class Test5 extends Activity {
private static final String TAG = "Test5";
private MySurfaceView mMSV;
private ImageView mRectView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMSV = new MySurfaceView(this);
mRectView = new ImageView(this);
ShapeDrawable sd = new ShapeDrawable(new RectShape());
sd.getPaint().setColor(Color.RED);
sd.setIntrinsicWidth(300);
sd.setIntrinsicHeight(100);
mRectView.setImageDrawable(sd);
FrameLayout frameLayout = new FrameLayout(this);
frameLayout.addView(mMSV);
frameLayout.addView(mRectView, new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT));
// I don't know why the following line prevents clipping during
// animation. It simply adds a vacuous View.
frameLayout.addView(new View(this));
setContentView(frameLayout);
} // onCreate
public class MySurfaceView extends SurfaceView implements
SurfaceHolder.Callback {
public MySurfaceView(Context context) {
super(context);
getHolder().addCallback(this);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Canvas can = mMSV.getHolder().lockCanvas();
can.drawColor(Color.GRAY);
mMSV.getHolder().unlockCanvasAndPost(can);
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
int arg3) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_UP) {
Log.v(TAG, String.format("ACTION_UP, w=%d, h=%d", mRectView
.getWidth(), mRectView.getHeight()));
Animation an = new TranslateAnimation(0f, 200f, 0f, 200f);
// Animation an = new RotateAnimation(0f, 90f);
an.setStartOffset(200);
an.setDuration(1000);
mRectView.startAnimation(an);
}
return true;
}
} // MySurfaceView
} // Test5
This is interesting... I guess that the size of the FrameLayout is changed when a vacuous view is added. Your frame layout does not fill the parent, I wonder if you change the layout params to fill parent, what would happen?
I simplified your code to this:
FrameLayout frameLayout = new FrameLayout(this);
frameLayout.addView(mMSV);
frameLayout.addView(mRectView, 50, 50);
frameLayout.addView(new View(this)); //expands frame layout
It seems that the FrameLayout size itself equal to the last added child view. If you set addView(new View(this)) before adding a rectangle then it reduces to 50 x 50 and animation is clipped. I assume that addView(new View(this)); expands FrameLayout to the full screen.
I don't know how you figured that out, but it seemed to work for me, too. I had just switched to using a SurfaceView, and noticed that the animations were getting clipped. Adding an empty View stopped the clipping.
the trick was setting setClipChildren to the
layout that enclosed the view.