Set onClickListener for custom view - android

I have created a custom view called Cell that draws a square. In my activity I create a 2d array of cells, hence giving a grid structure. Now the reason for this is, I want individual cells to respond to my clicks based on some value that they have. Say for eg, each cell has a boolean, and based on true of false I will color the cell.I tried doing this with one cell first. But the strange part is, the click event is triggered even when I click outside the cell.
More Information : I am creating all view in the onCreate method of the activity.
Let me know if you need more information.
Thanks in advance for your help !
Thought I will edit my original question for other references :) .
Activity
onCreate() {
super.onCreate(savedInstanceState);
LinearLayout masterLayout = new LinearLayout(this);
LinearLayout.LayoutParams params;
params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
masterLayout.setLayoutParams(params);
addCells();
setContentView(masterLayout);
}
function addCells() {
for(int i =0; i<2;i++) {
Cell cell = new Cell(this,i);
LinearLayout.LayoutParams viewParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
cell.setLayoutParams(viewParams);
masterLayout.addView(cell);
cell.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//Do Something here
}
});}}
Custom View :
Cell extends View {
boolean flag=false;
int cellNumber;
float xCoordinate=50;
float yCoordinate=50;
Cell(Context context, AttributeSet attrs) {
super(context, attrs);
}
Cell (Context context, int i) {
super(context);
cellNumber = i;
}
onDraw(Canvas c) {
paint.setColor(Color.RED);
paint.setStrokeWidth(3);
paint.setStyle(Paint.Style.STROKE);
xCoordinate = xCoordinate + 40*cellNumber;
c.drawRect(xCoordinate,yCoordinate,xCoordinate+40,yCoordinate+40, paint);
}}
This is a much simpler version that I was trying out. Now the strange part is, though I am adding two different instances of my custom view, the onDraw() is called just once (on exiting the onCreate() of the activity). From what I read, the onDraw() is called for every new view render. Please enlighten me on that front !
Thanks a lot!

I suppose you are not setting the onClickListener to the proper layout. Its some how being set to the parent of the element you want. Please share your code for us to zero in on the exact problem.

the click event is triggered even when I click outside the cell.
Probably you somehow forward the touch events to your cell, at least it is receiving them. In the onTouchEvent() method of your view is decided whether it is a click (and fire the click listener) or long click or drag, etc.
However, please post some code if this didn't help you identify the problem.

Related

How can I style Android tabs to get 3d look?

I want to create an Android tab view to look like this image:
I guess there are many ways to Rome, but I think I still haven't found the ideal one. My idea was to cut out a divider and an active divider and place them between the buttons. However, I don't know if this would be such a good solution because I still would need different styling for the first and last button. I already have a 9 patch for the surrounding (grey) container.
I've also thought about making a red 9 patch for the red bar, and than just style the selected button. The problem with this solution is that I'd still have to place the top diagonal white lines according to the number of buttons.
Does anyone have a better solution for me?
Here's another approach: to separate the header from the tabs. A bit complicated, yes, but the benefits are:
It allows you to define common tabs style;
Supports any number of buttons.
On this picture the buttons are of different width, so in reality an additional ImageView may be needed to the left of the header.
Let's create our header view as a LinearLayout. We can put upper dividers and stretchable gaps with the same layout_weight.
public class HeaderLayout extends LinearLayout {
public HeaderLayout(Context context) {
super(context);
initView();
}
public HeaderLayout(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public void setNumberOfColumns(int number) {
removeAllViews();
for (int i = 0; i < number; i++) {
addView(getColumnView(), getColumnLayoutParams());
// We don't need a divider after the last item
if (i < number - 1) {
addView(getDividerView(), getDividerLayoutParams());
}
}
}
private void initView() {
setBackgroundResource(R.drawable.header_bg);
}
private View getColumnView() {
return new View(getContext());
}
private View getDividerView() {
ImageView dividerView = new ImageView(getContext());
dividerView.setImageResource(R.drawable.header_divider);
dividerView.setScaleType(ImageView.ScaleType.FIT_XY);
return dividerView;
}
private LayoutParams getColumnLayoutParams() {
return new LayoutParams(0, LayoutParams.MATCH_PARENT, 1.0f);
}
private LayoutParams getDividerLayoutParams() {
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
}
}
Where R.drawable.header_bg is a 9patch:
And R.drawable.header_divider is a simple (optionally transparent) bitmap:
For me personally, making different background for the first and the last button is the least difficult solution, but it depends on the actual task.

Android: How can I disable touchability?

I'm using android 2.0. I have a view (just a sipmle linearlayout with an image as background), which contains 3 imagebuttons. When I touch any part of this view, my buttons are not touchable any more. As they are disabled! How can I disable the touchability of the background? I just want to be able to touch the buttons even if I put my finger on the other parts of the view. Is that possible?
The code sample:
public class myView extends LinearView {
public myView(Context context) {
super(context);
}
public setView(Context context) {
setBackgroundDrawable(backImg);
setOrientation(LinearLayout.HORIZONTAL);
setGravity(Gravity.CENTER);
setScrollContainer(false);
ImageButton imgBtn0 = new ImageButton(context);
imgBtn0.setBackgroundColor(Color.TRANSPARENT);
imgBtn0.setBackgroundDrawable(imgBtnD0);
imgBtn0.setDrawingCacheEnabled(true);
imgBtn0.setOnTouchListener(new TouchListener(context, id0));
...
addView(imgBtn0, 0);
addView(imgBtn1, 1);
addView(imgBtn2, 2);
}
}
you can disable the touch of the linearlayout using android:clicable="false" but how will you figure out which image button to be clicked if the user clicks in the background?

setImageMatrix only working in Touch Event Android

I'm trying to make a custom map with a modified relativelayout.
I'm using matrices and touch events.
First Problem
Every setImageMatrix() outside of my Touch Event are not doing anything but the ones in the event are working.
The problem is that I need to be able to set points on the map before the user touches the screen.
I've tried invalidate() on pretty much every view and it's not doing anything.
Second problem
I have made a custom class extending ImageView and it's not displaying at all.
Constructor:
public OverlayPoint(Context context,JSONObject obj) {
super(context);
this.obj = obj;
this.setImageResource(R.drawable.interet);
this.setScaleType(ImageView.ScaleType.MATRIX);
this.setLayoutParams(new LayoutParams
(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
myMatrix = new Matrix();
}
The call in the extended relativelayout :
public void addPoint(JSONObject obj) throws JSONException
{
OverlayPoint vv = new OverlayPoint(getContext(),obj);
Upoint pp = new Upoint(obj.getDouble("latitude"),obj.getDouble("longitude"));
vv.setXY(pp.getX(), pp.getY());
this.addView(vv);
myOverlays.add(vv);
Log.d("Overlay","Point added to array");
Log.d("Overlay", myOverlays.toString());
GlobalState gs = (GlobalState) ((VTTMatapediaActivity)this.getContext()).getApplication();
gs.addPoint(obj);
this.invalidate();
}
Edit: Forgot to mention I was using a ViewFlipper to flip views. But I juste tried Waiting for the animation to finish to call a setImageMatrix and nothing happens...
Thanks

How to add view components dynamically from activity

I am attempting to create a user interface dynamically. I have successfully create a view and loaded my background image. I have created two additional small view items to display on the background. My problem is that I have not been able to find any advice/instruction that tells me how to draw the small views. It seems that it should be a trivial exercise and I am guessing it is just finding the correct referencing. Hope someone out there can point me in the right direction.
Here is my Activity:
public class GhostActivity extends Activity implements OnTouchListener
{
private DrawView ghostView;
public Card mCard1, mCard2;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
// ToDo add your GUI initialization code here
super.onCreate(savedInstanceState);
// requesting to turn the title OFF
requestWindowFeature(Window.FEATURE_NO_TITLE);
// making it full screen
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
ghostView = new DrawView(this);
setContentView(ghostView);
//get the window size
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
Context context = getApplicationContext();
//create view items with initial positions
Point startPoint;
startPoint = new Point();
startPoint.x = 5;
startPoint.y = 3;
mCard1 = new Card(context, 1, R.drawable.bol_geel, startPoint);
startPoint.x = 5;
startPoint.y = 43;
mCard2 = new Card(context, 2, R.drawable.bol_rood, startPoint);
//now display them on the ghostView *****************HOW?
// set the callbacks
ghostView.setOnTouchListener(this);
mCard1.setOnTouchListener(this);
mCard2.setOnTouchListener(this);
}
and here is the View;
public class DrawView extends View
{
Drawable bg ;
public DrawView(Context context) {
super(context);
//setFocusable(true);
Drawable bg = this.getResources().getDrawable(R.drawable.bubbleblue480x800);
setBackgroundDrawable(bg);
}
#Override protected void onDraw(Canvas canvas) {
// canvas.drawColor(0x0000000); //if you want another background color
//draw on the canvas
}
}
edit: I believe my problem is needing to pass a pointer to the ghostView canvas. what makes me think that is if I create the children within ghostView then call their .draw method they appear exactly as I would expect.
#Override protected void onDraw(Canvas canvas) {
canvas.drawColor(0x0000000); //if you want another background color
//draw the cards on the canvas
mCard1.draw(canvas);
mCard2.draw(canvas);
}
so at this point I am wondering how to get a reference pointer to the ghostView canvas.
To be honest I am finding the whole Activity - View relationship confusing.
Edit: I have taken a different approach based on detail in this tutorial
http://www.kellbot.com/2009/06/android-hello-circle/
It uses a FrameLayout and it seems I can achieve my objective.
To add view dynamically to view your class must extends from ViewGroup or LinearLayout class then you will able to call method addView.
Inside your ghost view first add a layout e.g Linear or Relative. Then only you could able to add views inside that layout you cant simply add a view to a xml file.
Or you can create a dynamic layout then only u can add view inside that layout.
RelativeLayout relative= new RelativeLayout(findViewById(R.id.your relativeLayoutID));
relative.addView(child);
child could be anything button textview and widget.

Android: Change APIDemo example AnimateDrawable.java to have a ClickEvent-Handler

I love the API Demo examples from the Android webpage and used the AnimateDrawable.java to
get started with a WaterfallView with several straight falling images which works great. Now I like the images to stop when they are clicked. I found out that Drawables can't handle events so I changed AnimateDrawable and ProxyDrawable to be extended from View instead and added a Click-Event-Listener and Handler on the parent WaterfallView. The animation still works great, but the handler doesn't, probably because in AnimateDrawable the whole canvas is shifted when the drawabled are animated. How can I change that example so that I can implement an event handler? Or is there a way to find out where exactly my AnimateDrawables are in the view?
So the more general question is: How to add an Event Listener / Handler to an animated View?
Here are my changes to the example above:
AnimateView and ProxyView instead of AnimateDrawable and ProxyDrawable
ProxyView extended from View and all super calls changed to mProxy
I commented out mutate()
The context is still the main Activity which is passed down in the constructors
In the constructors of AnimateView setClickable(true) and setFocusable(true) are called
And here is the important source code of the parent/main WaterfallView:
public class WaterfallView extends View implements OnClickListener {
private Context mContext;
// PictureEntry is just a value object to manage the pictures
private Vector<PictureEntry> pictures = new Vector<PictureEntry>();
public WaterfallView(Context context) {
super(context);
mContext = context;
pictures.add(new PictureEntry(context.getResources().getDrawable(R.drawable.sample_0)));
pictures.add(new PictureEntry(context.getResources().getDrawable(R.drawable.sample_1)));
pictures.add(new PictureEntry(context.getResources().getDrawable(R.drawable.sample_2)));
pictures.add(new PictureEntry(context.getResources().getDrawable(R.drawable.sample_3)));
pictures.add(new PictureEntry(context.getResources().getDrawable(R.drawable.sample_4)));
pictures.add(new PictureEntry(context.getResources().getDrawable(R.drawable.sample_5)));
pictures.add(new PictureEntry(context.getResources().getDrawable(R.drawable.sample_6)));
pictures.add(new PictureEntry(context.getResources().getDrawable(R.drawable.sample_7)));
}
#Override
protected void onDraw(Canvas canvas) {
if(!setup) {
for(PictureEntry pic : pictures) pic.setAnimation(createAnimation(pic));
setup = true;
}
canvas.drawColor(Color.BLACK);
for(PictureEntry pic : pictures) pic.getAnimateView().draw(canvas);
invalidate();
}
private Animation createAnimation(PictureEntry picture) {
Drawable dr = picture.getDrawable();
dr.setBounds(0, 0, dr.getIntrinsicWidth(), dr.getIntrinsicHeight());
Animation an = new TranslateAnimation(0, 0, -1*dr.getIntrinsicHeight(), this.getHeight());
an.setRepeatCount(-1);
an.initialize(10, 10, 10, 10);
AnimateView av = new AnimateView(mContext, dr, an);
av.setOnClickListener(this);
picture.setAnimateView(av);
an.startNow();
return an;
}
#Override
public void onClick(View v) {
Log.i("MyLog", "clicked "+v);
}
}
Are you going to be clicking widgets(buttons, checkboxes, etc)? Or do you want to be able to click anywhere? I think you want the latter. So in that case you'll need this method:
#Override
public boolean onTouchEvent(MotionEvent event) {
// do stuff with your event
}
This method is ONLY called when the event is NOT handled by a view, so I think you may have to remove some of your onClickListener stuff. Refer to here for more info. And as always, experiment.

Categories

Resources