Button subclass onClick not responding - java

I am trying to create a subclass of Button. The code is as below
package com.comnet.bookshelf;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.Button;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
public class myButton extends Button implements OnClickListener{
Paint mainPaint;
int colorArray[];
int colorArrayAlt[];
boolean touch=false;
Rect bound;
public myButton(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
mainPaint=new Paint();
bound=new Rect();
defaultColorIndexArray();
}
public myButton(Context context, AttributeSet attrs)
{
super(context, attrs);
mainPaint=new Paint();
bound=new Rect();
defaultColorIndexArray();
}
public myButton(Context context)
{
super(context);
mainPaint=new Paint();
bound=new Rect();
defaultColorIndexArray();
}
private void defaultColorIndexArray(){
colorArray=new int[]{
0xFFd28181, //1
0xFFd48787, //2
0xFFd68d8d, //3
0xFFd89292, //4
0xFFda9898, //5
0xFFdc9e9e, //6
0XFFdea2a2, //7
0XFFe0a8a8, //8
0xFFe2adad, //9
0XFFe3b1b1, //10
0XFFe4b4b4, //11
0XFFe6b9b9, //12
0XFFe7bdbd, //13
0XFFe9c0c0, //14
0XFFeac3c3, //15
0XFFebc6c6, //16
0XFFebc7c7, //17
0XFFecc9c9, //18
0XFFeccaca, //19
0XFFeccaca, //20
0XFFeccbcb, //21
0XFFeccbcb //22
};
colorArrayAlt=new int[]{
0XFFeccbcb, //22
0XFFeccbcb, //21
0XFFeccaca, //20
0XFFeccaca, //19
0XFFecc9c9, //18
0XFFebc7c7, //17
0XFFebc6c6, //16
0XFFeac3c3, //15
0XFFe9c0c0, //14
0XFFe7bdbd, //13
0XFFe6b9b9, //12
0XFFe4b4b4, //11
0XFFe3b1b1, //10
0xFFe2adad, //9
0XFFe0a8a8, //8
0XFFdea2a2, //7
0xFFdc9e9e, //6
0xFFda9898, //5
0xFFd89292, //4
0xFFd68d8d, //3
0xFFd48787, //2
0xFFd28181 //1
};
}
public void setButtonColorIndexArray(int carray[], int carray_alt[]){
}
#Override
protected void onDraw(Canvas canvasObject) {
super.onDraw(canvasObject);
int draw_color[];
if(touch==false)
draw_color=colorArray;
else
draw_color=colorArrayAlt;
int width=canvasObject.getWidth();
int height=canvasObject.getHeight();
double colorcount=44;
double divheight=height;
double f=colorcount/divheight;
double step=0;
for(int i=0;i<height;i++,step+=f){
int next=(int) Math.round(step);
if(next>43) next=43;
else if(next<0)next=0;
if(next<22){
mainPaint.setColor(draw_color[next]);
canvasObject.drawLine(0, i, width, i, mainPaint);
}
else{
mainPaint.setColor(draw_color[43-next]);
canvasObject.drawLine(0, i, width, i, mainPaint);
}
//int color=;
mainPaint.setColor(getCurrentTextColor());
String str=this.getText().toString();
//mainPaint.setColor(Color.WHITE);
mainPaint.setStyle(Style.FILL);
//canvasObject.drawPaint(mainPaint);
mainPaint.setColor(Color.BLACK);
mainPaint.setTextSize(20);
mainPaint.getTextBounds(str, 0, str.length(), bound);
int x=(width-(bound.right-bound.left))/2;
int y=(height+(bound.bottom-bound.top))/2;
canvasObject.drawText(str, x, y, mainPaint);
}
}
#Override
public boolean onTouchEvent(MotionEvent ev){
if(ev.getAction()==MotionEvent.ACTION_DOWN){
//Log.i("Click", "ACTION_DOWN");
touch=true;
this.invalidate();
}
else if(ev.getAction()==MotionEvent.ACTION_UP){
touch=false;
this.invalidate();
}
return true;
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Log.i("Clicked", "Clicked");
}
}
Everything but one is working as I expected.
onClick is not responding at all. The code is as below:
((myButton)inflatedLayout.findViewById(R.id.DeleteButton)).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
DeleteTheEntireBook();
}
});
The button with default class is working fine
If you have any further question, let me know.

The problem is You have overridden onTouchEvent.
Mark these words:
You should return false in your OnTouchListener then your OnClickListener will be also handled.
So you might think, I will just do my thing there and return false so I can receive clicks too. If you do so, it will work, but you wont be subscribed to other upcoming touch events (ACTION_MOVE, ACTION_UP) Therefore only option is to return true there, but then you wont receive any click events as we said previously.
So you need to perform the click manually in the ACTION_UP with performClick()
Tested and working code :
#Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
// Log.i("Click", "ACTION_DOWN");
touch = true;
this.invalidate();
} else if (ev.getAction() == MotionEvent.ACTION_UP) {
touch = false;
this.invalidate();
// KEY LINE
performClick();
}
return true;
}
Hope it helps ツ

in the constructor, add the onClickListener,
and no need to ((myButton)inflatedLayout.findViewB...
public myButton(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
mainPaint=new Paint();
bound=new Rect();
defaultColorIndexArray();
setOnClickListener(this);
}
then the overridden onClick in myButton class should be called once the button is clicked.

View.OnClickListener :Interface definition for a callback to be invoked when a view is clicked.
Can you use this Code:
((myButton)inflatedLayout.findViewById(R.id.DeleteButton)).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DeleteTheEntireBook();
}
});

Related

Vertical SeekBar Android, how to update the slider position with SetProgress()

I know I'm not the first one having issue with a VerticalSlider on android but even though I recall struggling to make it work in the first place this is the first time that I have a partially working setProgress().
So here is the thing.
The blue line that represents the slider is properly updated but the tiny "button" that is supposed to moved as well does not move at all. (see images)
The blue line is moving according to to the values I send, but the "button" is not. It is moving a little, but not at all following the blue line---which is right. (If you have better terms for "button" and blue-line, feel free to edit. Progress line maybe?)
So this is the code I have for the vertical slider:
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.SeekBar;
public class VerticalSeekBar extends SeekBar {
public VerticalSeekBar(Context context) {
super(context);
}
public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public VerticalSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(h, w, oldh, oldw);
}
#Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
protected void onDraw(Canvas canvas) {
canvas.rotate(-90);
canvas.translate(-getHeight(), 0);
super.onDraw(canvas);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled())
return false;
boolean result = false;
if (event.getAction() != MotionEvent.ACTION_MOVE) {
// Prevent duplicate haptic feedback events (due to
// setProgress() below)
boolean hf = isHapticFeedbackEnabled();
setHapticFeedbackEnabled(false); {
// This is required for OnSeekBarChangeListener.on{Start,Stop}TrackingTouch()
result = super.onTouchEvent(event);
} setHapticFeedbackEnabled(hf);
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_MOVE:
// Vertical scrolling
setProgress(getMax() - (int)(getMax() * event.getY()/getHeight()));
onSizeChanged(getWidth(), getHeight(), 0, 0);
result = true;
break;
}
return result;
}
public void customSetProgress(int progress) {
setProgress(progress);
onSizeChanged(getWidth(), getHeight(), 0, 0);
}
}
And this how I'm updating the slider:
float value = //... Get the value here from other computations
// We need to use int for the slider
final int step = 1;
final int max = (int)MAXPRECISION * 100;
final int min = (int)MINPRECISION * 100;
final double initialPosition = (double)max ;
final int valueInt = (int) (value * 100) ;
final VerticalSeekBar sliderPrecision = (VerticalSeekBar)findViewById(R.id.verticalSliderPrecision);
sliderPrecision.setProgress(valueInt);
sliderPrecision.setMax( (max - min) / step ); //To make sure it is updated as seen in some SO post.
I am pretty confident that my VerticalSlider class is good as I have been able to use it properly years ago. So there is surely something wrong with the rest of the code, but I can't find what that may be.
As for the images here they are:
So I found out that this is solved by calling onSizeChanged(getWidth(), getHeight(), 0, 0);
So I have created an updated VerticalSeekBar that works just fine now.
I do hope it will help other people struggling with them.
Here is the updated class:
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.SeekBar;
public class VerticalSeekBar extends SeekBar {
public VerticalSeekBar(Context context) {
super(context);
}
public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public VerticalSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(h, w, oldh, oldw);
}
#Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
protected void onDraw(Canvas canvas) {
canvas.rotate(-90);
canvas.translate(-getHeight(), 0);
super.onDraw(canvas);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled())
return false;
boolean result = false;
if (event.getAction() != MotionEvent.ACTION_MOVE) {
// Prevent duplicate haptic feedback events (due to
// setProgress() below)
boolean hf = isHapticFeedbackEnabled();
setHapticFeedbackEnabled(false); {
// This is required for OnSeekBarChangeListener.on{Start,Stop}TrackingTouch()
result = super.onTouchEvent(event);
} setHapticFeedbackEnabled(hf);
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_MOVE:
// Vertical scrolling
setProgress(getMax() - (int)(getMax() * event.getY()/getHeight()));
onSizeChanged(getWidth(), getHeight(), 0, 0);
result = true;
break;
}
return result;
}
public void customSetProgress(int progress) {
setProgress(progress);
onSizeChanged(getWidth(), getHeight(), 0, 0);
}
}

Android create a marquee text

I'm developing a news application, I want to use a breaking news banner at the bottom of the layout.
The layout is :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:gravity="bottom">
<com.example.test.ScrollTextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="20dp"
android:background="#00ff00"
android:id="#+id/scrolltext">
</com.example.test.ScrollTextView>
</LinearLayout>
And the Java code is :
package com.example.test;
import android.annotation.TargetApi;
import android.app.Activity;
import android.graphics.Color;
import android.os.Build;
import android.os.Handler;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.TranslateAnimation;
import android.widget.*;
import java.util.Map;
public class Newstest extends Activity
{
TextView label1;
#Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.news);
ScrollTextView scrolltext=(ScrollTextView) findViewById(R.id.scrolltext);
scrolltext.setText("dddddddddddddddddddddddddddddddddd sajd asjd lksdddddddddddddddddddddddddddddddddd sajd asjd lksdddddddddddddddddddddddddddddddddd sajd asjd lksdddddddddddddddddddddddddddddddddd sajd asjd lks");
scrolltext.setTextColor(Color.BLACK);
scrolltext.startScroll();
}
}
I'm using a ScrollTextView class :
package com.example.test;
import android.content.Context;
import android.graphics.Rect;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.animation.LinearInterpolator;
import android.widget.Scroller;
import android.widget.TextView;
public class ScrollTextView extends TextView {
// scrolling feature
private Scroller mSlr;
// milliseconds for a round of scrolling
private int mRndDuration = 10000;
// the X offset when paused
private int mXPaused = 0;
// whether it's being paused
private boolean mPaused = true;
/*
* constructor
*/
public ScrollTextView(Context context) {
this(context, null);
// customize the TextView
setSingleLine();
setEllipsize(null);
setVisibility(INVISIBLE);
}
/*
* constructor
*/
public ScrollTextView(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.textViewStyle);
// customize the TextView
setSingleLine();
setEllipsize(null);
setVisibility(INVISIBLE);
}
/*
* constructor
*/
public ScrollTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// customize the TextView
setSingleLine();
setEllipsize(null);
setVisibility(INVISIBLE);
}
/**
* begin to scroll the text from the original position
*/
public void startScroll() {
// begin from the very right side
mXPaused = -1 * getWidth();
// assume it's paused
mPaused = true;
resumeScroll();
}
/**
* resume the scroll from the pausing point
*/
public void resumeScroll() {
if (!mPaused)
return;
// Do not know why it would not scroll sometimes
// if setHorizontallyScrolling is called in constructor.
setHorizontallyScrolling(true);
// use LinearInterpolator for steady scrolling
mSlr = new Scroller(this.getContext(), new LinearInterpolator());
setScroller(mSlr);
int scrollingLen = calculateScrollingLen();
int distance = scrollingLen - (getWidth() + mXPaused);
int duration = (new Double(mRndDuration * distance * 1.00000
/ scrollingLen)).intValue();
setVisibility(VISIBLE);
mSlr.startScroll(mXPaused,0, distance, 0, duration);
invalidate();
mPaused = false;
}
/**
* calculate the scrolling length of the text in pixel
*
* #return the scrolling length in pixels
*/
private int calculateScrollingLen() {
TextPaint tp = getPaint();
Rect rect = new Rect();
String strTxt = getText().toString();
tp.getTextBounds(strTxt, 0, strTxt.length(), rect);
int scrollingLen = rect.width() + getWidth();
rect = null;
return scrollingLen;
}
/**
* pause scrolling the text
*/
public void pauseScroll() {
if (null == mSlr)
return;
if (mPaused)
return;
mPaused = true;
// abortAnimation sets the current X to be the final X,
// and sets isFinished to be true
// so current position shall be saved
mXPaused = mSlr.getCurrX();
mSlr.abortAnimation();
}
#Override
/*
* override the computeScroll to restart scrolling when finished so as that
* the text is scrolled forever
*/
public void computeScroll() {
super.computeScroll();
if (null == mSlr) return;
if (mSlr.isFinished() && (!mPaused)) {
this.startScroll();
}
}
public int getRndDuration() {
return mRndDuration;
}
public void setRndDuration(int duration) {
this.mRndDuration = duration;
}
public boolean isPaused() {
return mPaused;
}
}
What I want is that the text will scroll from left to right, the opposite of what the class does. I tried changing parameters in the line mSlr.startScroll(mXPaused,0, distance, 0, duration); but the scrolling direction remains the same. Any help please
Have you tried marquee attribute? This should scroll text that doesn't fit the view
<TextView
android:layout_width="10dip"
android:layout_height="wrap_content"
android:text="FooBar FooBar FooBar FooBar"
android:singleLine="true"
android:ellipsize="marquee" />
http://developer.android.com/reference/android/widget/TextView.html#attr_android:ellipsize
From looking at the API docs:
http://developer.android.com/reference/android/widget/Scroller.html#startScroll(int, int, int, int)
Seems you can pass it negative numbers to scroll the opposite way, so try:
mSlr.startScroll(mXPaused, 0, -distance, 0, duration);
Marquee attribute only works for focused views, so use this view instead of textview beside android:ellipsize="marquee":
public class TextViewMarquee extends TextView
{
public TextViewMarquee(Context context, AttributeSet attrs)
{
super(context, attrs, R.attr.marqueeStyle);
}
public TextViewMarquee(Context context, AttributeSet attrs, int style)
{
super(context, attrs, style);
}
#Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect)
{
if(focused) super.onFocusChanged(focused, direction, previouslyFocusedRect);
}
#Override
public void onWindowFocusChanged(boolean focused)
{
if(focused) super.onWindowFocusChanged(focused);
}
#Override
public boolean isFocused()
{
return true;
}
}

Android: extend Linearlayout, but need same for RelativeLayout. Duplicate code unavoidable?

I have this code:
public class CopyOfLinearLayoutEntry extends LinearLayout implements Checkable {
private CheckedTextView _checkbox;
private Context c;
public CopyOfLinearLayoutEntry(Context context) {
super(context);
this.c = context;
setWillNotDraw(false);
}
public CopyOfLinearLayoutEntry(Context context, AttributeSet attrs) {
super(context, attrs);
this.c = context;
setWillNotDraw(false);
}
#Override
protected void onDraw(Canvas canvas) {
Paint strokePaint = new Paint();
strokePaint.setARGB(200, 255, 230, 230);
strokePaint.setStyle(Paint.Style.STROKE);
strokePaint.setStrokeWidth(12);
Rect r = canvas.getClipBounds();
Rect outline = new Rect(1, 1, r.right - 1, r.bottom - 1);
canvas.drawLine(r.left, r.top, r.right, r.top, strokePaint);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
// find checked text view
int childCount = getChildCount();
for (int i = 0; i < childCount; ++i) {
View v = getChildAt(i);
if (v instanceof CheckedTextView) {
_checkbox = (CheckedTextView) v;
}
}
}
#Override
public boolean isChecked() {
return _checkbox != null ? _checkbox.isChecked() : false;
}
#Override
public void setChecked(boolean checked) {
if (_checkbox != null) {
_checkbox.setChecked(checked);
}
}
#Override
public void toggle() {
if (_checkbox != null) {
_checkbox.toggle();
}
}
}
Now I also need a version for RelativeLayout, so I would duplicate the class file and replace "extends LinearLayout" with "extends RelativeLayout". I think that would be bad, because I do not want any duplicate code.
How would I go about achieving my goal, seeing that Java does not allow multiple inheritance?
I read something about the composition design pattern, but I am not sure how to implement that.
Maybe someone could give me a starting point as to how to most elegantly solve this problem?
You don't need to extend both to avoid duplicate code. You can do something like this:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckedTextView;
public class GenericLayout extends ViewGroup{
private CheckedTextView _checkbox;
public GenericLayout(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
Paint strokePaint = new Paint();
strokePaint.setARGB(200, 255, 230, 230);
strokePaint.setStyle(Paint.Style.STROKE);
strokePaint.setStrokeWidth(12);
Rect r = canvas.getClipBounds();
Rect outline = new Rect(1, 1, r.right - 1, r.bottom - 1);
canvas.drawLine(r.left, r.top, r.right, r.top, strokePaint);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
// find checked text view
int childCount = getChildCount();
for (int i = 0; i < childCount; ++i) {
View v = getChildAt(i);
if (v instanceof CheckedTextView) {
_checkbox = (CheckedTextView) v;
}
}
}
public boolean isChecked() {
return _checkbox != null ? _checkbox.isChecked() : false;
}
public void setChecked(boolean checked) {
if (_checkbox != null) {
_checkbox.setChecked(checked);
}
}
public void toggle() {
if (_checkbox != null) {
_checkbox.toggle();
}
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
}
}
public class Linear extends LinearLayout {
GenericLayout generic;
public Linear(Context context) {
super(context);
// TODO Auto-generated constructor stub
generic = new GenericLayout(context);
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
generic.onDraw(canvas);
}
...
}
public class Relative extends RelativeLayout{
GenericLayout generic;
public Relative(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
generic.onDraw(canvas);
}
...
}
Of what I have learned and been using, there are two ways:
You can do what you are trying to avoid (duplicate the class file and replace "extends LinearLayout" with "extends RelativeLayout")
You can create 2 interfaces and 1 class: One interface that extends LinearLayout, another one for extending RelativeLayout and the class implementing the methods and variables of the extending interfaces.
I hope that helps a little
You have to rethink your approach.
Seems like you are are using layout to control VIEW logic. Unfortunately your question does not have too much information about what you are trying to achieve.
You have few possibilities:
implement LAYOUT proxy / delegate with the custom logic (bad approach IMO)
make a dedicated HANDLER class to control your VIEW objects... these will be independent on the LAYOUT
make your VIEW object and use VIEW object instead of LAYOUT (probably the way to go)

Change TextView Color Depending On Text

Using onDraw, I want to make a custom text view that changes color depending on its text value. For example, if the text value is "hello" I want it to be red and if it says "bye" I want it to be green. Any helps greatly appreciated.
I'm not necessarily sure why you want to do this in onDraw(). Unless you have a really good reason to set up a custom TextView/EditText, that's not necessary.
To simplify your situation, you can implement a TextWatcher to do this, and in onTextChanged(), you can set the color by comparing the string values using .equals().
Here is an example of your theoretical situation:
final EditText yourEditText = /* findViewById maybe? */;
yourEditText.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s.equalsIgnoreCase("hello"))
yourEditText.setTextColor(Color.RED);
else if (s.equalsIgnoreCase("bye"))
yourEditText.setTextColor(Color.GREEN);
else // if it says neither "hello" nor "bye"
yourEditText.setTextColor(Color.BLACK);
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// Nothing needs to happen here
}
public void afterTextChanged(Editable s) {
// Nothing needs to happen here
}
});
If you feel its necessary to maintain this in onDraw(), simply extract the code from onTextChanged() and change yourEditText to this, or place it in the constructor instead:
public class YourTextView extends TextView { // Or extends EditText, doesn't matter
public YourTextView(Context context) {
this(context, null, 0);
}
public YourTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public YourTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
addTextChangedListener(new TextWatcher() {
// Copy the TextWatcher code from the example above, replacing "yourEditText" with "YourTextView.this"
});
}
// ... Rest of your class
}
I figured out how to do it in a more creative way using onDraw.
public class MagnitudeTextView extends TextView {
public MagnitudeTextView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public MagnitudeTextView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public MagnitudeTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
/*
* (non-Javadoc)
*
* #see android.widget.TextView#onDraw(android.graphics.Canvas)
*/
#Override
protected void onDraw(Canvas canvas) {
int height = getMeasuredHeight();
int width = getMeasuredWidth();
int px = width / 2;
int py = height / 2;
Paint Red = new Paint(Paint.ANTI_ALIAS_FLAG);
Red.setColor(Color.RED);
Paint White = new Paint(Paint.ANTI_ALIAS_FLAG);
White.setColor(Color.DKGRAY);
Paint Yellow = new Paint(Paint.ANTI_ALIAS_FLAG);
Yellow.setARGB(210, 105, 30, 0);
Paint Blue = new Paint(Paint.ANTI_ALIAS_FLAG);
Blue.setColor(Color.BLUE);
float textWidth = Red.measureText(String.valueOf(getText()));
String g = String.valueOf(getText());
if (g.startsWith("3") || g.startsWith("4")) {
canvas.drawText(String.valueOf(getText()), px - textWidth / 2, py,
White);
}
if (g.startsWith("6") || g.startsWith("5") || g.startsWith("7")
|| g.startsWith("8")) {
canvas.drawText(String.valueOf(getText()), px - textWidth / 2, py,
Yellow);
}
if (g.startsWith("9") || g.startsWith("10")) {
canvas.drawText(String.valueOf(getText()), px - textWidth / 2, py,
Red);
}
// super.onDraw(canvas);
}
}
You can overwrite setText() and set the color using setTextColor().
You can do it inside onDraw as well, but it's not worth the weigth, as it may pass many times inside onDraw.
You can implement TextWatcher and use onTextChanged()
More about it here in the Android Docs
Use this to get the text:
TextView text = (TextView)findViewById(R.id.textid);
String value = text.getText().toString();
Then check what the text is and change the color :
if (value.equals("hello")) {
text.setBackgroundColor(yourcolor);
}

custom ondraw method is not working

I am working on application in which i want to display different text on image.when i touch the different position.I am working on the different image.In my program I have used one class to change the image and one class to draw a text on the image.
my activity class is as follow......
public class VideosActivity extends Activity implements OnTouchListener
{
//DrawView draw;
float a=0;
float b=0;
ImageView image;
MotionEvent event;
Button back ;
Button next;
TextView t;
String info = "";
int count =0;
FirstImage i;
ViewFlipper c;
Infoview v;
String huma="human";
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.videos_layout);
i=new FirstImage(this);
c=(ViewFlipper) findViewById(R.id.viewFlipper1);
back = (Button) findViewById(R.id.button1);
next = (Button) findViewById(R.id.button2);
t=(TextView) findViewById(R.id.textView1);
if(count==0)
i.changeImage(R.drawable.human );
i.invalidate();
c.addView(i,0);
c.setOnTouchListener(this);
c.onTouchEvent(event);
}
public void pageinfo(float a,float b)
{
t.setText(Float.toString(a)+"x"+Float.toString(b)+"y");
i.display( a, b);
}
public boolean onTouch(View v, MotionEvent me)
{
// TODO Auto-generated method stub
switch(me.getAction())
{
case MotionEvent.ACTION_DOWN:
a=me.getX();
b= me.getY();
pageinfo(a,b);
break;
case MotionEvent.ACTION_MOVE:
a=me.getX();
b= me.getY();
pageinfo(a,b);
break;
case MotionEvent.ACTION_UP:
a=me.getX();
b= me.getY();
pageinfo(a,b);
break;
case MotionEvent.ACTION_OUTSIDE:
a=me.getX();
b= me.getY();
pageinfo(a,b);
break;
default: return false;
}
return true;
}
}
the class which is used to change the image is as follow...
public class FirstImage extends LinearLayout {
ImageView i;
int x;
Infoview v;
String huma ="human";
public FirstImage(Context context) {
super(context);
v=new Infoview(context);
i= new ImageView (context);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(android.view.ViewGroup.LayoutParams.WRAP_CONTENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
addView(i, lp);
addView(v,lp);
}
public FirstImage(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected void changeImage(int id){
i.setImageResource(id);
x=id;
}
public int getSrc() {
// TODO Auto-generated method stub
return x;
}
public void display(float a, float b) {
// TODO Auto-generated method stub
if(i.getId()==R.drawable.human){
v.updateInfo(huma, a, b);
i.invalidate();
v.invalidate();
}
}
}
class which is used for drawing text on the image is as follow..
public class Infoview extends View {
String info = "";
float x = 0; //init value
float y = 0; //init value
int color = Color.WHITE;
public Infoview(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public Infoview(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public Infoview(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);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setColor(color);
paint.setStrokeWidth(2);
paint.setTextSize(30);
canvas.drawLine(x-10, y, x+10, y, paint);
canvas.drawLine(x, y-10, x, y+10, paint);
canvas.drawText(info, x, y, paint);
}
public void updateInfo(String t_info, float t_x, float t_y){
info = t_info;
x = t_x;
y = t_y;
invalidate();
}
public void clearInfo(){
info = "";
x = 0;
y = 0;
invalidate();
}
I am not understanding why it is not displaying text on the image ......I think in the time of image drawing i am using one layout.so i have to include drawing class(Infoview) into that layout to...
If any one thinking that i am re asking this question then i am sorry ...
any help is appreciated...
I did get time to read the full code but if you override onDraw, you are not supposed to invoke super.onDraw() inside that method since that will mean that the base class will draw everything first.

Categories