Here is my unanswered question:
Add new item count to icon on button - Android
Basically I want to display "new" counts on top. I see it as overlaying some view over existing button. How this can be done?
Easiest thing to do is:
Use a RelativeLayout with layout_height and layout_width set to WRAP_CONTENT.
Put one Button into the RelativeLayout with layout_height and layout_width set to WRAP_CONTENT.
Add an ImageView into the RelativeLayout aligned to PARENT_TOP and PARENT_RIGHT and set the visibility to GONE.
Then you can simply set the ImageView's drawable to the appropriate count image and set the visibility to VISIBLE.
Ok here is what i'd do:
Create a custom control that extends button. I'm not going to do the pretty graphics for you but this will give you the basic idea:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.widget.Button;
public class CounterButton extends Button{
protected int count=0;
protected final Paint myTextPaint = new Paint();
protected final Paint myCirclePaint = new Paint();
public CounterButton(Context context, AttributeSet attrs) {
super(context, attrs);
this.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.ic_dialog_email));
this.myCirclePaint.setARGB(150, 255, 0, 0);
this.myTextPaint.setARGB(150, 255, 255, 255);
}
#Override
protected void onDraw(Canvas canvas) {
if(count!=0){
canvas.drawCircle((float) (this.getWidth()*.75), (float) (this.getHeight()*.4), this.getHeight()/5, myCirclePaint);
canvas.drawText(Integer.toString(count), (float) (this.getWidth()*.75), (float) (this.getHeight()*.4), this.myTextPaint);
}
}
}
Clean up the sizing of your text you draw, the circle positioning (and add a border etc) and you have a custom control. You could further extend it so you could set the background in xml or dynamically and you have a reusable control with a number counter in a circle.
then in your code you could do:
CounterButton cb=(CounterButton) findViewById(R.id.whateverYouGaveItInXML);
cb.count=SomeNewNumber;
cb.invalidate;
the invalidate will redraw the image with the new value in the circle.
I used a button in the event you want to have it clickable easily and all that - but you could just as easily extend view if you are just doing a view.
Related
I am using that "hack".
I have read here in stackoverflow.
#Override
public void draw(Canvas canvas) {
for (int i = 0; i < 20; i++) {
super.draw(canvas);
}
}
But my border still smoothie,I wanna put a large and solid border on all my TextView (I already have my component extend a textview).
I have a selector in text color when I click in this text the text color need to change.(It was already working,but I tried to apply another alternative using canvas,in this alternative,I lost this comportment).
This page solve your problem, you can custom the style:
How do I put a border around an Android textview?
You can set a shape drawable (a rectangle) as background for the view.
<TextView android:text="Some text" android:background="#drawable/back"/>
And rectangle drawable back.xml (put into res/drawable folder):
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<solid android:color="#ffffff" />
<stroke android:width="1dip" android:color="#4fa5d5"/>
</shape>
You can use #00000000 for the solid color to have a transparent background. You can also use padding to separate the text from the border. for more information see: http://developer.android.com/guide/topics/resources/drawable-resource.html
Your current solution (the hack) is working fine, you just have to tweak 2 parameters accordingly to get a better "solid" shadow effect.
Parameters
The 1st parameter is the shadow radius of the TextView. This parameter decides how "wide" the blur (shadow) effect will spread behind your letter.
The 2nd parameter is the repeat counter of the for loop that wraps around your TextView's onDraw(...) method. Higher repeat count will get you a more "solid" shadow by trading off the performance.
"Solid" shadow
The rule here is, increment on shadow radius (↑) must always accompany with increment on repeat counter (↑) to achieve the "solid" shadow effect.
Similarly, if you want to gain performance by reducing repeat counter (↓), you have to decrease shadow radius (↓) as well.
Solid shadow TextView
package com.example.solidshadowtext;
import android.content.Context;
import android.graphics.Canvas;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.widget.TextView;
public class SolidShadowTextView extends TextView {
/**
* Shadow radius, higher value increase the blur effect
*/
private static final float SHADOW_RADIUS = 10f;
/**
* Number of times a onDraw(...) call should repeat itself.
* Higher value ends up in more solid shadow (but degrade in performance)
* This value must be >= 1
*/
private static final int REPEAT_COUNTER = 10000;
// Shadow color
private static final int SHADOW_COLOR = 0xff000000;
public SolidShadowTextView(Context context) {
super(context);
init();
}
public SolidShadowTextView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
#Override
protected void onDraw(Canvas canvas) {
for (int i = 0; i < REPEAT_COUNTER; i++) {
super.onDraw(canvas);
}
}
#Override
public void setShadowLayer(float radius, float dx, float dy, int color) {
// Disable public API to set shadow
}
private void init() {
super.setShadowLayer(SHADOW_RADIUS, 0, 0, SHADOW_COLOR);
}
}
Sample
My variable hz is null, why is this?
code:
HorizontalScrollView hz = (HorizontalScrollView) findViewById((R.id.horizontalScrollView2));
hz.addView(imageView, params);
hz.setBackgroundColor(Color.BLACK);
// Show this layout in our activity.
ScrollView scrollView = (ScrollView) findViewById(R.id.scrollView);
setContentView(scrollView);
xml:
<ScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/scrollView">
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/horizontalScrollView2">
<AbsoluteLayout
android:layout_width="1000dp"
android:layout_height="1000dp"
android:id="#+id/al"/>
</HorizontalScrollView>
</ScrollView>
Also it won't allow me to have my absoluteLayout within the horizontalScrollView. I'm trying to make a drawable area bigger than the screen size that you can scroll both up and down, where I will be drawing a board game board. Can someone give me a hand to get this drawable area set up? Thanks.
All code of my activity:
package com.example.btf.game;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
public class SplashScreen extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// We'll be creating an image that is 100 pixels wide and 200 pixels tall.
int width = 1000;
int height = 3000;
// Create a bitmap with the dimensions we defined above, and with a 16-bit pixel format. We'll
// get a little more in depth with pixel formats in a later post.
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
// Create a paint object for us to draw with, and set our drawing color to blue.
Paint paint = new Paint();
paint.setColor(Color.BLUE);
// Create a new canvas to draw on, and link it to the bitmap that we created above. Any drawing
// operations performed on the canvas will have an immediate effect on the pixel data of the
// bitmap.
Canvas canvas = new Canvas(bitmap);
// Fill the entire canvas with a red color.
canvas.drawColor(Color.RED);
// Draw a rectangle inside our image using the paint object we defined above. The rectangle's
// upper left corner will be at (25,50), and the lower left corner will be at (75,150). Since we set
// the paint object's color above, this rectangle will be blue.
canvas.drawRect(25, 50, 75, 150, paint);
// In order to display this image in our activity, we need to create a new ImageView that we
// can display.
ImageView imageView = new ImageView(this);
// Set this ImageView's bitmap to the one we have drawn to.
imageView.setImageBitmap(bitmap);
// Create a simple layout and add our image view to it.
RelativeLayout layout = new RelativeLayout(this);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.CENTER_IN_PARENT);
// LinearLayout container = (LinearLayout) findViewById(R.id.container);
HorizontalScrollView hz = (HorizontalScrollView) findViewById((R.id.horizontalScrollView2));
hz.addView(imageView, params);
hz.setBackgroundColor(Color.BLACK);
// Show this layout in our activity.
ScrollView scrollView = (ScrollView) findViewById(R.id.scrollView);
setContentView(scrollView);
}
}
Your views are null because there are not a part of activity at time you're trying to get them through findViewById() method.
You need to call setContentView() before "finding" views and pass your xml layout in it: setContentView(R.layout.my_acitivty_layout)
Follows is an SSCCE to understand animation timing, extracted from a much more complicated example. What this example when completed should do is create a circle and change its fill color between red and green every second. Right now it just draws a red circle and then nothing else. I've tried placing Runnable, Timer, Thread, and Handler code in various locations but it never seems to do anything. Another problem I've encountered in run() methods is the need for references to Canvas and the current color and the only way I've obtained them is by creating member data for them which, especially in the case of Canvas, seems like a bad idea. For what I'm ultimately doing, rotation and translation of graphic objects, SampleView and the accompanying Canvas seems to be almost certainly necessary so I want to leave SampleView in place. I think that's part of the problem, most examples of animation I've encountered place the timing code in an Activity but that won't work cleanly since the inner View's canvas must be used to update the color (unless I'm missing something).
Inside run methods I used variations on code like this.
if (color == Color.RED)
color = Color.GREEN;
else color = Color.RED;
canvas.drawOval(rectF, p);
hand.postDelayed(run, GET_DATA_INTERVAL);
Those references to color and canvas have been a pain.
package com.example.circles;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
private static class SampleView extends View {
public SampleView(Context context) {
super(context);
setFocusable(true);
p = new Paint();
}
Paint p;
int color;
RectF rectF = new RectF(0, 0, 50, 50);
#Override
protected void onDraw(Canvas canvas) {
p.setStyle(Paint.Style.FILL);
color = Color.RED;
p.setColor(color);
canvas.drawOval(rectF, p);
}
}
}
I'm new to the Android SDK so I'm trying to figure this out. I have read the documentation and a text book and they haven't been particularly helpful in this matter.
I'm just trying to draw a simple rectangle in a linear layout on the screen. I can't get the shape to show up, however, when I add text to this layout in the same fashion, the text does show up. What am I missing?
package jorge.jorge.jorge;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RectShape;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class ShapesActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ShapeDrawable rect = new ShapeDrawable(new RectShape());
rect.getPaint().setColor(Color.GREEN);
ImageView view1 = new ImageView(this);
view1.setImageDrawable(rect);
LinearLayout frame = (LinearLayout)findViewById(R.id.linear1);
frame.addView(view1);
// TextView tx = new TextView(this);
//
// tx.setText("Hello World");
//
// frame.addView(tx);
}
}
The Shape is usually used for making a background to some View. Its width and height is the same of the view that is using it. Then, if this view has no width and height, It'll have no width and height, too.
Basically, I think that your ImageView has no width and height, then it's invisible.
You can see how to set it programatically here:
Set ImageView width and height programmatically?
But, I recomend you to make the layout in XML's way.
I am using RelativeLayout to position views at precise locations on the screen. This works as expected when using a view that say, draws a rectangle. But when using Android views like EditText, they are drawn shorter than specified by about 8 units. Clicking outside of the drawn EditText (but within the parameters specified by RelativeLayout) will, in fact, hit the EditText.
Here is some code to illustrate what I mean:
package com.DrawDemo;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.RelativeLayout;
public class DrawDemo extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
RelativeLayout l = new RelativeLayout(this);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(100,100);
lp.leftMargin = 50;
lp.topMargin = 50;
DemoView demoview = new DemoView(this);
l.addView(demoview, lp);
EditText editText = new EditText(this);
l.addView(editText, lp);
setContentView(l);
}
private class DemoView extends View
{
public DemoView(Context context)
{
super(context);
}
#Override protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.GREEN);
canvas.drawPaint(paint);
}
}
}
If you execute this, you will notice that the EditText is noticeably shorter than the rectangle. I've tried mucking with onMeasure, setMinimumXXX, and just about everything else I can think of. So far, the only thing that works with some level of success is to just add 8 or so pixels to the height (8 seems to work better than trying a percentage of the height).
Next task will be to step into the source but was wondering if somebody has already solved this.
Thanks.
It's just because of the actual EditText background image that's used. Buttons are the same way, for some reason Google decided to draw the 9-patch background images with some extra transparent padding pixels. Really, the only solution, if it's a problem, would be to draw your own 9-patch, or modify the existing Android 9-patch to remove the extra pixels.