Creating Custom ImageView - android

I create a custom image view by extending ImageView that just draws some text on the screen, however I don't see anything painted in the Emulator Screen, but the log messages and the printlns get printed in the log console. Am I not doing something?
This is my activity
public class HelloAndroidActivity extends Activity
{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// setContentView(R.layout.main);
CustomImageView myView = new CustomImageView(getApplicationContext());
System.out.println("Setting the view");
myView.invalidate();
setContentView(myView);
System.out.println("Calling invalidate");
}
}
This is my CustomImageView
public class CustomImageView extends ImageView
{
/**
* #param context
*/
public CustomImageView(Context context)
{
super(context);
// TODO Auto-generated constructor stub
setBackgroundColor(0xFFFFFF);
}
/**
* #param context
* #param attrs
*/
public CustomImageView(Context context, AttributeSet attrs)
{
super(context, attrs);
// TODO Auto-generated constructor stub
}
/**
* #param context
* #param attrs
* #param defStyle
*/
public CustomImageView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas)
{
// TODO Auto-generated method stub
super.onDraw(canvas);
System.out.println("Painting content");
Paint paint = new Paint(Paint.LINEAR_TEXT_FLAG);
paint.setColor(0x0);
paint.setTextSize(12.0F);
System.out.println("Drawing text");
canvas.drawText("Hello World in custom view", 100, 100, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
// TODO Auto-generated method stub
Log.d("Hello Android", "Got a touch event: " + event.getAction());
return super.onTouchEvent(event);
}
}
Even the log message in the onTouchEvent() gets printed, but nothing is painted.
This is my main.xml that has the layout
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android" android:id="#+id/AbsoluteLayout">
</AbsoluteLayout>

Use color values Color.WHITE or Color.BLACK instead of hexa values.

Have you checked your canvas size? An image view expects the bitmap/drawable to return its size and based on the scaletype flags, determine the size of the view. I don't see anything in your code that determines the size of the view for layout needs.
-Rick

Related

Android - Adding custom surfaceView to xml defined surfaceView not working

I am trying to add a custom surfaceView class to a surfaceView that has been declared in a xml layout. The problem is that I cannot get the custom class add the the xml defined surfaceView. Some how it just does not start.
This is my code:
MainActivity
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sineWaveSurfaceView = (SineWaveSurfaceView) findViewById(R.id.surfaceView);
}
MainActivity Layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<mark.dijkema.android.eindopdracht.SineWaveSurfaceView
android:id="#+id/surfaceView"
android:layout_width="fill_parent"
android:layout_height="100dp"
android:layout_marginTop="20dp" />
<ListView
android:id="#+id/song_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp" >
</ListView>
</RelativeLayout>
SineWaveSurfaceView Class
public class SineWaveSurfaceView extends SurfaceView implements SurfaceHolder.Callback
{
private Context context;
public SineWaveSurfaceView(Context context)
{
super(context);
// TODO Auto-generated constructor stub
this.context = context;
getHolder().addCallback(this);
Log.e("constructor", "done");
}
public SineWaveSurfaceView(Context context, AttributeSet attrs)
{
super(context, attrs);
// TODO Auto-generated constructor stub
}
public SineWaveSurfaceView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
protected void OnDraw(Canvas canvas, int value)
{
//canvas.drawColor(Color.WHITE);
Paint paint = new Paint();
paint.setColor(Color.WHITE);
float y = Float.valueOf(String.valueOf(value));
for(float x = 0; x < 200; x += 0.1f)
{
canvas.drawPoint(x, y, paint);
}
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3)
{
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder arg0)
{
// TODO Auto-generated method stub
Log.e("start", "started");
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0)
{
// TODO Auto-generated method stub
}
}
The problem is that the Log.e("constructor", "done"); in the constructor of the SineWaveSurfaceView is not even showing up.
What am I doing wrong, because when I do something like
sineWaveSurfaceView = new sineWaveSurfaceView(this);
then it works, but it is not attached to the surfaceView defined in the xml layout.
As veryBadalloc explained in the comments, it appeared that inflating from xml starts the second constructor, thus my code was working after all.

setting onClickListener on views drawn on a canvas

So basically I have some image views drawn over my canvas, but when I try to set up onclick listeners and try to handle events, it doesn't work.
public class DrawView extends View implements OnClickListener{
Paint paint = new Paint();
RectF rf = new RectF(30, 30, 80, 80);
BallView ball = new BallView(getContext());
Bitmap bmp = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.ic_launcher);
public DrawView(Context context) {
super(context);
}
#Override
public void onDraw(Canvas canvas) {
ball.setOnClickListener(this);
ball.draw(canvas);
canvas.drawBitmap(bmp, 110, 10, paint);
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getContext(), "Mock", Toast.LENGTH_SHORT).show();
}
}
BallView.java
public class BallView extends ImageView {
Paint b = new Paint();
public BallView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public void onDraw(Canvas c){
b.setColor(Color.BLUE);
c.drawCircle(50, 50, 40, b);
}
}
Basically the answer is: Your view is not receiving touch events, because it's not in views hierarchy, so click callback is also not called. Actually, view should be in View hierarchy (in other words, added to some upper level view and finally, to the window) in order to participate is user interactions.
So, if You want to implement somthing covering Your view, then it should be ViewGroup or shouldn't be related to view at all and be some abstract container.
E.g. using the way below click works without any issues (but You will need second view or modify BallView to draw bmp):
DrawView:
public class DrawView extends FrameLayout implements View.OnClickListener {
BallView ball = new BallView(getContext());
public DrawView(Context context) {
this(context, null, 0);
}
public DrawView(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public DrawView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
addView(ball);
ball.setOnClickListener(this);
}
#Override
public void onClick(View v) {
Toast.makeText(getContext(), "Mock", Toast.LENGTH_SHORT).show();
}
}
BallView class stays the same.
Layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.ruinalst.performance.tests.views.DrawView
android:id="#+id/oscillator"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true" />
</RelativeLayout>

How to get background color of EditText on android

I would like to get color of EditText, I could set it by setBackgroundColor, but there is not getBackgroundColor function
I found this
EditText edtxt;
edtxt.setBackgroundColor(Color.GREEN);
PaintDrawable drawable;
Log.d(TAG,"1");
drawable = (PaintDrawable)edtxt.getBackground();
if(drawable.getPaint().getColor()==(int)Color.GREEN).........
Log.d(TAG,"2");
but its not working and crashing
05-29 19:20:27.526: E/AndroidRuntime(20255): Caused by: java.lang.ClassCastException: android.graphics.drawable.StateListDrawable cannot be cast to android.graphics.drawable.PaintDrawable
This should work for API level 11 and up
ColorDrawable drawable = (ColorDrawable)edtxt.getBackground();
if(drawable.getColor()==(int)Color.GREEN)
System.out.println("It's Green");
If you want it to wok on earlier APIs, I would suggest using a Custom EditText and overriding the setBackgroundColor(int color) method.
public class NewEditText extends EditText {
private int color;
public NewEditText(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public NewEditText(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public NewEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
#Override
public void setBackgroundColor(int color) {
// TODO Auto-generated method stub
this.color=color;
super.setBackgroundColor(color);
}
public int getBackgroundColor() {
return color;
}
}
Now in the Layout use:
<com.aneesh.mypackage.NewEditText
android:layout_width="fill_parent"
android:id="#+id/customview"
android:layout_height="wrap_content"/>
and your Activity Code will change to
NewEditText custView = (NewEditText)findViewById(R.id.customview);
custView.setBackgroundColor(Color.GREEN);
if(custView.getBackgroundColor()==(int)Color.GREEN)
System.out.println("It's green");
If you are setting the color in runtime it could be better to save some kind of flag (boolean for example) to know which is the background color of the edit text.

How to have a Viewgroup containing multiple ImageButton in android?

While creating a custom Viewgroup,is it possible to have multiple Imagebutton within it?
is it possible to place Image buttons in our own position.
If all these are possible,how to call the click listener which extending this viewgroup?
My ViewGroup have to look like this image
EDIT 1:
public class CustomViewGroup extends ViewGroup{
public CustomViewGroup(Context context) {
super(context);
setWillNotDraw(false);
//addImageView();
// TODO Auto-generated constructor stub
}
public CustomViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(false);
//addImageView();
// TODO Auto-generated constructor stub
}
public CustomViewGroup(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs,
defStyle);
setWillNotDraw(false);
//addImageView();
// TODO Auto-generated constructor stub
}
#Override
protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
// TODO Auto-generated method stub
System.out.println("onLayout");
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
drawBackground(canvas);
addImageView();
//super.onDraw(canvas);
}
private void drawBackground(Canvas canvas)
{
Bitmap background =BitmapFactory.decodeResource(getContext().getResources(), R.drawable.shape_quarter_circle);
canvas.drawBitmap(background, 0,0, null);
}
private void addImageView()
{
ImageView imageOne = new ImageView(getContext());
imageOne.setImageDrawable(getContext().getResources().getDrawable(R.drawable.round_icon));
//imageOne.setWillNotDraw(false);
addView(imageOne);
requestLayout();
}
I am trying to draw a background and place some ImageView on the top of the background.
In this code Background image is getting displayed correctly. but i could not see the ImageView drawn upon it.
Am i going in the correct path?
all the things you said are possible.
you just use
yourViewGroup.setOnClickListener()
for your view group click listener.

Android Drawing

I am learning how to code with Android but I am still confused bby the way it works, I am able to create simple draws like circles and stuff but now i want to paint the circle multiple times with a delay of 2 seconds.. I would appreciatge if you experts can help me improve my code and to put the stuff in the correct place
public class ColorChanges extends Activity {
DrawCircle dc;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
drawCircleToCanvas()
}
void drawCircleToCanvas()
{
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
dc.postInvalidate();
}
};
Thread updateUI = new Thread()
{
public void run() {
dc = new DrawCircle(this); //this line does not work
dc.setBackgroundColor(Color.WHITE);
setContentView(dc);
handler.sendEmptyMessage(0);
}
};
updateUI.start();
}
}
public class DrawCircle extends View {
Paint p1 = new Paint();
Paint p2 = new Paint();
Paint p3 = new Paint();
Paint pAll[] = new Paint[3];
public DrawCircle(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public DrawCircle(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public DrawCircle(Context context) {
super(context);
p1.setStyle(Paint.Style.STROKE);
p1.setColor(Color.GREEN);
p1.setStyle(Paint.Style.FILL);
p2.setStyle(Paint.Style.STROKE);
p2.setColor(Color.BLUE);
p2.setStyle(Paint.Style.FILL);
p3.setStyle(Paint.Style.STROKE);
p3.setColor(Color.YELLOW);
p3.setStyle(Paint.Style.FILL);
pAll[1] = p1;
pAll[2] = p2;
pAll[3] = p3;
// TODO Auto-generated constructor stub
}
#Override
public void onDraw(Canvas canvas)
{
for (int i = 0; i < pAll.length;i++)
{
canvas.drawCircle(200, 200, 100, pAll[i]);
}
}
}
If you want to draw the same circle with its color changing over the time (each 2 seconds as you mentionned) you should use an Handler
in order to create a timer and to switch the paint at each time it is called.
Do not forget to call the invalidate function inside your custom view, as this function ask the system to redraw the screen.

Categories

Resources