Android - How to click through transparent area of custom view - java

In order to position a button in the exact spot on all devices, I have created it with a custom view. The button takes up a small part of the screen but the actual view takes up most of the screen. All the area around the button is transparent. How can I allow the user to click through the transparent area to buttons underneath but still click the button area on the view?
Here is the relavant code:
public class MainActivity extends AppCompatActivity {
final float dotScale = 0.3f;
Dot dot1, dot2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
RelativeLayout myLayout = (RelativeLayout) findViewById(R.id.mainView);
MyView myView = new MyView(this);
myLayout.addView(myView);
// Two dots are created.
dot1 = new Dot(this);
dot1.xOffset = 2.9f;
dot1.yOffset = 3.3f;
myLayout.addView(dot1);
dot2 = new Dot(this);
dot2.xOffset = -2.4f;
dot2.yOffset = 1.1f;
myLayout.addView(dot2);
// Makes dots clickable
dot1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!dot1.isClicked) {
dot1.animate().setDuration(300).setInterpolator(new AnticipateInterpolator())
.scaleXBy(dotScale).scaleYBy(dotScale).alpha(1.0f);
dot1.isClicked = true;
}
}
});
dot2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!dot2.isClicked) {
dot2.animate().setDuration(300).setInterpolator(new AnticipateInterpolator())
.scaleXBy(dotScale).scaleYBy(dotScale).alpha(1.0f);
dot2.isClicked = true;
}
}
});
}
.......
//custom view for Dots
class Dot extends View {
int radius;
float xOffset;
float yOffset;
boolean isClicked = false;
public Dot(Context context) {
super(context);
setClickable(true);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int x = getWidth();
int y = getHeight();
double ratio = (547d / 828d);
float circleX = (float)((x / 2) - (y * ratio) / xOffset);
float circleY = (float)(y / yOffset);
radius = (int)((float)y/13);
setPivotX(circleX);
setPivotY(circleY);
Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawCircle(circleX, circleY, radius, paint);
}
}

You should set your view clickable and don't override onTouch at all or just return false from it. Return false means that you didn't consume event and it will be forwarded to the next element in view hierarchy.

Related

Android drawing

I am following a tutorial, and have the following code, but I want to modify it a little bit, so I want when its clicked inside the circle it must be filled with another collor, how I can do it, as I am just learning this concept I dont have any idea of how it can be done :/
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyView(this));
}
public class MyView extends View {
public MyView(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int x = getWidth();
int y = getHeight();
int radius;
radius = 100;
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
canvas.drawPaint(paint);
paint.setColor(Color.parseColor("#CD5C5C"));
canvas.drawCircle(x / 2, y / 2, radius, paint);
}
}
}
you have to add a touch listener on your view
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View myView = new MyView(this);
setContentView(myView);
myView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
float x = event.getX();
float y = event.getY();
//if(x==... your code here
invalidate(); //this repaints the view
return false;
}
});
}
}

How do I display a image button in front of an image in Android?

I am really new to programming and I've got a problem I've been making a game and all the the borders and backgrounds are images and I've been trying to find a away to display an image button so I can do a settings menu but I don't know what to do next please help. this is how I've done my button
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageButton myButton = new ImageButton(this);
myButton.setImageResource(R.drawable.settings);
myButton.setId(1);
RelativeLayout myLayout = new RelativeLayout(this);
RelativeLayout.LayoutParams buttonParams =
new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
myLayout.addView(myButton, buttonParams);
setContentView(myLayout);
myButton.setOnClickListener(
new View.OnClickListener() {
public void onClick(View v) {
onButtonClick(v);
}
});
}
public void onButtonClick(View v) {
//do something when button is clicked.
PopupMenu popup = new PopupMenu(this, v);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.contextitems, popup.getMenu());
popup.show();
}
and this is how I'm displaying the images
#Override
public void draw(Canvas canvas) {
final float scaleFactorX = getWidth() / (WIDTH * 1.f);
final float scaleFactorY = getHeight() / (HEIGHT * 1.f);
if (canvas != null) {
final int savedState = canvas.save();
canvas.scale(scaleFactorX, scaleFactorY);
bg.draw(canvas);
if (!dissapear) {
player.draw(canvas);
}
//draw smokepuffs
for (Smokepuff sp : smoke) {
sp.draw(canvas);
}
//draw missiles
for (Missile m : missiles) {
m.draw(canvas);
}
//draw topborder
for (TopBorder tb : topborder) {
tb.draw(canvas);
}
//draw botborder
for (BotBorder bb : botborder) {
bb.draw(canvas);
}
//draw explosion
if (started) {
explosion.draw(canvas);
}
drawText(canvas);
canvas.restoreToCount(savedState);
}
}
You have to use Layer List (drawable).
<bitmap
android:src="#drawable/your_photo"
android:gravity="center" />

How to set the same OnClickListener to all(multiple) ImageView(s)

I am making some kind of puzzle game where there will be a lot of blocks that are made of ImageView(s). Now in this case, I have only setOnClickListener to imageView1, now rather than me writing the same block of setOnClickListener for each ImageView, how do I write the setOnclickListener once for all the ImageView(s) ??
Here's the sample code
MainActivity.java
public class MainActivity extends Activity {
ImageView imageView1, imageView2, imageView3;
int x, y;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
x = 0;
y = 0;
imageView1 = (ImageView) findViewById(R.id.image1);
imageView2 = (ImageView) findViewById(R.id.image2);
imageView3 = (ImageView) findViewById(R.id.image3);
imageView1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TranslateAnimation animation = new TranslateAnimation(0, 0, 0, 50);
animation.setDuration(1000);
animation.setFillAfter(false);
animation.setAnimationListener(new MyAnimationListener());
imageView1.startAnimation(animation);
x += 0;
y += 50;
}
});
}
private class MyAnimationListener implements Animation.AnimationListener {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
imageView1.clearAnimation();
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(imageView1.getWidth(),
imageView1.getHeight());
lp.setMargins(x, y, 0, 0);
imageView1.setLayoutParams(lp);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
}
}
All suggestions and improvements of my codes are greatly welcomed. Thanks in advance.
You can try to create your listener in a variable and then assign it to each ImageView. Something like this:
imageView1 = (ImageView) findViewById(R.id.image1);
imageView2 = (ImageView) findViewById(R.id.image2);
imageView3 = (ImageView) findViewById(R.id.image3);
View.OnClickListener listener= new View.OnClickListener() {
#Override
public void onClick(View v) {
TranslateAnimation animation = new TranslateAnimation(0, 0, 0, 50);
animation.setDuration(1000);
animation.setFillAfter(false);
animation.setAnimationListener(new MyAnimationListener());
if(v==imageView1)
imageView1.startAnimation(animation);
else if(v==imageView2)
imageView2.startAnimation(animation);
else if(v==imageView3)
imageView3.startAnimation(animation);
x += 0;
y += 50;
}
};
imageView1.setOnClickListener(listener);
imageView2.setOnClickListener(listener);
imageView3.setOnClickListener(listener);
Try to use this:
imageView1 = (ImageView) findViewById(R.id.image1);
imageView2 = (ImageView) findViewById(R.id.image2);
imageView3 = (ImageView) findViewById(R.id.image3);
View.OnClickListener listener= new View.OnClickListener() {
#Override
public void onClick(View v) {
TranslateAnimation animation = new TranslateAnimation(0, 0, 0, 50);
animation.setDuration(1000);
animation.setFillAfter(false);
ImageView vista=(ImageView) v;
animation.setAnimationListener(new MyAnimationListener(vista));
vista.startAnimation(animation);
x += 0;
y += 50;
}
};
imageView1.setOnClickListener(listener);
imageView2.setOnClickListener(listener);
imageView3.setOnClickListener(listener);
private class MyAnimationListener implements Animation.AnimationListener {
ImageView selected;
public MyAnimationListener(ImageView vista)
{
selected=vista;
}
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
selected.clearAnimation();
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(selected.getWidth(),
selected.getHeight());
lp.setMargins(x, y, 0, 0);
selected.setLayoutParams(lp);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
}
You can implement your custom OnClickListener with the Activity like below,
public class MainActivity extends Activity implements View.OnClickListener{
ImageView imageView1, imageView2, imageView3;
int x, y;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
x = 0;
y = 0;
imageView1 = (ImageView) findViewById(R.id.image1);
imageView2 = (ImageView) findViewById(R.id.image2);
imageView3 = (ImageView) findViewById(R.id.image3);
imageView1.setOnClickListener(this);
imageView2.setOnClickListener(this);
imageView3.setOnClickListener(this);
}
#Override
public void onClick(View v) {
TranslateAnimation animation = new TranslateAnimation(0, 0, 0, 50);
animation.setDuration(1000);
animation.setFillAfter(false);
animation.setAnimationListener(new MyAnimationListener(v));
v.startAnimation(animation);
x += 0;
y += 50;
}
private class MyAnimationListener implements Animation.AnimationListener {
private View mView;
public MyAnimationListener(View v)
{
this.mView = v;
}
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
mView.clearAnimation();
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(mView.getWidth(),
mView.getHeight());
lp.setMargins(x, y, 0, 0);
mView.setLayoutParams(lp);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
}
}
Create a distinct listener:
View.OnclickListener listener = new View.OnClickListener() {
#Override
public void onClick(View v) {
TranslateAnimation animation = new TranslateAnimation(0, 0, 0, 50);
animation.setDuration(1000);
animation.setFillAfter(false);
animation.setAnimationListener(new MyAnimationListener());
v.startAnimation(animation);
x += 0;
y += 50;
}
};
then set the listener to your views:
imageView1.setOnClickListener(listener);
imageView2.setOnClickListener(listener);
imageView3.setOnClickListener(listener);
You can always extend your class as activity and implement OnClickListener. Then you should override the OnClick function. It takes a view as parameter that you can check if it is your intended view (i.e. your Imageviews)
eg:
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
/**
* Created by Rohan on 15-09-2015.
*/
public class MyActivity extends Activity implements View.OnClickListener{
ImageView imageView1, imageView2, imageView3;
int x, y;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
x = 0;
y = 0;
imageView1 = (ImageView) findViewById(R.id.image1);
imageView2 = (ImageView) findViewById(R.id.image2);
imageView3 = (ImageView) findViewById(R.id.image3);
imageView1.setOnClickListener(this);
imageView2.setOnClickListener(this);
imageView3.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if(v.getId() == R.id.image1 || v.getId() == R.id.image2 || v.getId() == R.id.image3 ){
//Do your stuff
}
}
}
Let MainActivity implements OnClickListener and call
public class MainActivity extends Activity implements OnClickListener {
ImageView imageView1, imageView2, imageView3;
int x, y;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
x = 0;
y = 0;
imageView1 = (ImageView) findViewById(R.id.image1);
imageView2 = (ImageView) findViewById(R.id.image2);
imageView3 = (ImageView) findViewById(R.id.image3);
imageView1.setOnClickListener(this);
imageView2.setOnClickListener(this);
imageView3.setOnClickListener(this);
#Override
public void onClick(View v) {
switch(v.getId()){
case R.id.image1:
TranslateAnimation animation = new TranslateAnimation(0, 0, 0, 50);
animation.setDuration(1000);
animation.setFillAfter(false);
animation.setAnimationListener(new MyAnimationListener());
imageView1.startAnimation(animation);
x += 0;
y += 50;
break;
case R.id.image2:
break;
case R.id.image3:
break;
}
}
}
Although your code is in Java, there is an easy way in kotlin that someone could find useful. You can create an extension function for a list of views.
Extension function:
fun List<View>.setOnClickListener(onClickView: () -> Unit) {
this.forEach { it.setOnClickListener { onClickView.invoke() } }
}
How to use it:
listOf(ImageView, ImageView2, ImageView3).setOnClickListener {
// put your action here
}

Android move object to touch

I'm kinda new to building apps on Android. I do have some Java developing experience, but the project I do now is first on Android.
I'm building a basic cards game, and I want the card to move to the specific location I touch.
I did it, and the card moves to the touch point, but once the animation is over it bounces back to starting position.
I added a Image re-position code, but now it begins the animation from that point.
any ideas, anyone?
the code I did is:
public class FinallyActivity extends Activity {
/** Called when the activity is first created. */
EditText DBG;
ImageView iv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
DBG = (EditText) findViewById(R.id.editText1);
iv = (ImageView) findViewById(R.id.imV1);
}
private void RunAnimations(MotionEvent event) {
// Animation b = AnimationUtils.loadAnimation(this,R.anim.cardtrans);
int xStart, yStart, dx, dy;
xStart = iv.getLeft();
yStart = iv.getTop();
Animation b = new TranslateAnimation(Animation.ABSOLUTE,0,Animation.ABSOLUTE,event.getX()-50,
Animation.ABSOLUTE,0,Animation.ABSOLUTE,event.getY()- 105);
b.setDuration(3000);
iv.clearAnimation();
iv.startAnimation(b);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
RunAnimations(event);
}
iv.layout((int)event.getX()-25,(int) event.getY()-105,
(int)event.getX()+25,(int) event.getY()-35);
return true;
}
}
Thanks All!!
b.fillAfter(true)
http://developer.android.com/reference/android/view/animation/Animation.html#setFillAfter(boolean)
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = findViewById(R.id.subview);
imageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
xDown = event.getX();
yDown = event.getY();
break;
case MotionEvent.ACTION_MOVE:
float moveX,moveY;
moveX = event.getX();
moveY = event.getY();
float distanceX = moveX -xDown;
float distanceY = moveY -yDown;
imageView.setX(imageView.getX()+distanceX);
imageView.setY(imageView.getY()+distanceY);
break;
}
return true;
}
});
}

What is the mistake with my Android animation of my ImageView?

This code works only for the first animation. Though the final position of the ImageView is not exactly the point of the MotionEvent and the animation looks not smooth. The result of all other MotionEvents is actually no animation. The ImageView just appears at the point i touch the screen.
Here is the code.
ImageView image;
MyAnimationListener am;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
image = (ImageView)findViewById(R.id.imageView1);
am = new MyAnimationListener(image);
}
#Override
public boolean onTouchEvent(MotionEvent mEvent){
if(mEvent.getAction()==MotionEvent.ACTION_DOWN){
TranslateAnimation tAnimation = new TranslateAnimation(image.getX(),mEvent.getX(),image.getY(),mEvent.getY());
tAnimation.setDuration(500);
am.setCoordinates(mEvent.getX(), mEvent.getY());
tAnimation.setAnimationListener(am);
AnimationSet aSet = new AnimationSet(true);
aSet.addAnimation(tAnimation);
image.startAnimation(aSet);
}
return true;
}
And the interesting methods of MyAnimationListener.
ImageView i;
float x,y;
public MyAnimationListener(ImageView i){
this.i = i;
}
public void setCoordinates(float x, float y){
this.x = x;
this.y = y;
}
#Override
public void onAnimationEnd(Animation animation) {
i.setX(x);
i.setY(y);
}
Thanks in advance.
may be you need to do call a fillAfter so that the postion is not reset at the end of the animation. see link

Categories

Resources