Android: Custom view does draw - android

So I know there are a lot of questions like this, but none of the answers have had any effect.
I have a custom View that I am trying to put into a ScrollView (all programmatically). The ScrollView itself works fine, is where it needs to be, does what it's supposed to do and when tested by adding a TextView to it, still did what it was supposed to.
However when I create my custom View the view doesn't draw and it is as if nothing is there. The draw(Canvas canvas) method is never called (also tried with onDraw even though I don't know what the difference is but it still didn't work).
I have tried things such as setWillNotDraw(false) in the constructor, called View.invalidate() every time I want it to draw/redraw, nothing appears to be working.
Here is the relevant code:
ScrollView Initialized
sv = new ScrollView(env.getContext());
ScaledBounds sb = UsefulMethods.getScaledBounds(50, 200, BBEnvironment.WIDTH - 100, BBEnvironment.HEIGHT - 300);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(sb.getWidth(), sb.getHeight());
sv.setTranslationX(sb.getX());
sv.setTranslationY(sb.getY());
sv.setLayoutParams(params);
sv.setScrollbarFadingEnabled(false);
sv.setScrollBarSize(0);
sv.setBackgroundColor(Color.argb(150, 0, 255, 0));
Custom View Class
private class LevelSelectionView extends View {
private ArrayList<LevelButton> levelButtons;
public LevelSelectionView(Context context) {
super(context);
levelButtons = new ArrayList<LevelButton>();
int x = 20;
int y = 20;
for(int i = 0; i < 20; i++) {
levelButtons.add(new LevelButton(x, y, 100, 100, 10, i + 1));
levelButtons.get(i).unlock();
x += 100 + 20;
}
setWillNotDraw(false);
}
public void draw(Canvas canvas) {
super.draw(canvas);
System.out.println("is being called"); //except it isn't
Paint paint = new Paint();
paint.setAntiAlias(env.getCurrentSettings().getAntialias());
for(LevelButton lb : levelButtons)
lb.drawObject(canvas, paint);
}
}
Creating and adding custom view
LevelSelectionView lsView = new LevelSelectionView(sv.getContext());
lsView.setLayoutParams(new RelativeLayout.LayoutParams(sv.getLayoutParams().width, 1000));
lsView.setBackgroundColor(Color.argb(150, 0, 0, 255));
sv.addView(lsView);
Why is it not drawing and how do I get it to draw?

I tried like that and it works:
public class LevelSelectionView extends View {
private final static String TAG = LevelSelectionView.class.getSimpleName();
private final ArrayList<Button> mButtons;
private final Paint mPaint;
public LevelSelectionView(Context context) {
super(context);
mButtons = new ArrayList<Button>();
int x = 20;
int y = 20;
mPaint = new Paint();
// mPaint.setAntiAlias(env.getCurrentSettings().getAntialias());
Button myButton;
for (int i = 0; i < 20; i++) {
myButton = new Button(context);
myButton.setLayoutParams(new ViewGroup.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT));
mButtons.add(myButton);
// mButtons.get(i).unlock();
// x += 100 + 20;
}
setWillNotDraw(false);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (Button lb : mButtons)
Log.d(TAG, "is being called"); //except it isn't
// lb.drawObject(canvas, mPaint);
}
}
I don't know what is your LevelButton as it's a custom class.
I create the LevelSelectionView like that, using a FrameLayout but it's the same idea with the ScrollView:
FrameLayout container = (FrameLayout) findViewById(R.id.container);
LevelSelectionView view = new LevelSelectionView(this);
view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
container.addView(view);
Maybe your issue comes from the LevelButton or the context you use (as you use the Context from env to create the ScrollView and the Context of the ScrollView to create your custom class). You code is not clear as we don't know what is your env object as all your class are inner classes.

It looks like you need to properly implement onMeasure so the scrollview knows how tall that view is.

Related

Android: create a drawable that shows two lines of text one above the other in different fonts and sizes?

I want to create a single drawable that shows two lines of text, one above the other. Each line of text has to be in it's own typeface and textsize and it has to create a single drawable because I want to then set it as the drawable for a floating action button.
private void updateFloatingButtonText(String headlineText, String subHeadlineText, FloatingActionButton floatingActionButton) {
int headlineTextSize = getResources().getDimensionPixelSize(R.dimen.headlineTextSize);
int subheadlineTextSize = getResources().getDimensionPixelSize(R.dimen.subheadlineTextSize);
Spannable spannableStringHeadline = new SpannableString(headlineText);
Spannable spannableStringSubheadline = new SpannableString(subHeadlineText);
CustomTypefaceSpan boldSpan = new CustomTypefaceSpan("FontOne", FontCache.get("FontOne.ttf", this));
CustomTypefaceSpan regularSpan = new CustomTypefaceSpan("FontTwo", FontCache.get("FontTwo.ttf", this));
// set typeface headline
spannableStringHeadline.setSpan(regularSpan, 0,
headlineText.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE
);
// set typeface subtitle
spannableStringSubheadline.setSpan(boldSpan, 0,
subHeadlineText.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE
);
// set text size headline
spannableStringHeadline.setSpan(new AbsoluteSizeSpan(headlineTextSize), 0,
headlineText.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE
);
// set text size subline
spannableStringSubheadline.setSpan(new AbsoluteSizeSpan(subheadlineTextSize), 0,
subHeadlineText.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE
);
String finalString = TextUtils.concat(spannableStringHeadline, "\n", spannableStringSubheadline);
floatingActionButton.setImageDrawable([put the resulting drawable here]);
}
I've written this method that creates a single string formatted exactly the way that I need it, but I still have the issue of creating a drawable out of it.
I've tried to use this third party library, but although it displays the text in the correct typefaces it doesn't change the textsize of the lines of text.
https://github.com/devunwired/textdrawable
Is there a trivial (or nontrivial) way of doing this?
Solved by creating a new class that looks like this:
public class TextToDrawable extends Drawable {
private String headlineText = "";
private String subHeadlineText = "";
private final TextPaint headlinePaint = new TextPaint();
private final TextPaint subHeadlinePaint = new TextPaint();
public TextToDrawable(Context context, String headlineText, String subHeadlineText) {
this.headlineText = headlineText;
headlinePaint.setAntiAlias(true);
headlinePaint.setTypeface(FontCache.get("FontA.ttf", context));
headlinePaint.setTextSize(context.getResources().getDimensionPixelSize(R.dimen.headlineTextSize));
headlinePaint.setColor(ContextCompat.getColor(context, android.R.color.white));
headlinePaint.setStyle(Paint.Style.FILL);
headlinePaint.setTextAlign(Paint.Align.LEFT);
this.subHeadlineText = subHeadlineText;
subHeadlinePaint.setAntiAlias(true);
subHeadlinePaint.setTypeface(FontCache.get("FontB.ttf", context));
subHeadlinePaint.setTextSize(context.getResources().getDimensionPixelSize(R.dimen.subheadlineTextSize));
subHeadlinePaint.setColor(ContextCompat.getColor(context, android.R.color.white));
subHeadlinePaint.setStyle(Paint.Style.FILL);
subHeadlinePaint.setTextAlign(Paint.Align.LEFT);
}
#Override
public void draw(Canvas canvas) {
Rect headlineWidth = new Rect();
Rect subheadlineWidth = new Rect();
headlinePaint.getTextBounds(headlineText, 0, headlineText.length(), headlineWidth);
subHeadlinePaint.getTextBounds(subHeadlineText, 0, subHeadlineText.length(), subheadlineWidth);
Rect bounds = new Rect();
headlinePaint.getTextBounds(headlineText, 0, headlineText.length(), bounds);
int x = getBounds().width() / 2 - (headlineWidth.width()/2);
int y = (getBounds().height() / 2);
canvas.drawText(headlineText, x, y, headlinePaint);
x = getBounds().width()/2 - (subheadlineWidth.width()/2);
y += headlinePaint.getFontSpacing();
canvas.drawText(subHeadlineText, x, y, subHeadlinePaint);
}
#Override
public void setAlpha(int alpha) {
}
#Override
public void setColorFilter(ColorFilter colorFilter) {
}
#Override
public int getOpacity() {
return 0;
}
}
Then using the new class like this:
mFloatingActionButton.setImageDrawable(new TextToDrawable(this, "Headline", "Subheadline"));
This isn't a great solution because it only supports two lines of text - there's nothing dynamic going on here. However, I suppose it would be fairly easy to rewrite to support even more lines and more fonts and it solves the current problem.

RelativeLayout align parent bottom does not align at bottom

I have a custom circular layout using a relative layout:
public class CircularLayout extends RelativeLayout implements OnDragListener {
private DropCallback onDrop = null;
private ImageButton imageButton = null;
private ImageView imageViewBackgroundWave = null;
private int radius = -1;
private double step = -1;
private double angle = -1;
private static final int CENTER_ID = 111;
public CircularLayout(Context context, DropCallback onDrop, int radius, List<View> views) {
super(context);
this.onDrop = onDrop;
this.radius = radius;
this.step = (2 * Math.PI) / views.size();
this.initView(context, views);
}
private void initView(Context context, List<View> views) {
RelativeLayout.LayoutParams layoutParamsView = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
this.setLayoutParams(layoutParamsView);
RelativeLayout.LayoutParams layoutParamsImageview = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParamsImageview.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
layoutParamsImageview.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
this.imageViewBackgroundWave = new ImageView(this.getContext());
this.imageViewBackgroundWave.setLayoutParams(layoutParamsImageview);
this.imageViewBackgroundWave.setImageDrawable(this.getResources().getDrawable(R.drawable.background_wave));
this.addView(this.imageViewBackgroundWave);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
this.imageButton = new ImageButton(context);
this.imageButton.setId(CENTER_ID);
this.imageButton.setLayoutParams(layoutParams);
this.imageButton.setImageResource(R.drawable.ic_power_on);
this.imageButton.getBackground().setAlpha(0);
this.imageButton.setOnDragListener(this);
this.addView(this.imageButton);
for(View view : views) {
this.addView(this.placeView(view));
}
}
private View placeView(View view) {
view.measure(0, 0);
this.imageButton.measure(0, 0);
int x = (int)((view.getMeasuredWidth() / 2) + this.radius * Math.cos(this.angle));
int y = (int)((view.getMeasuredHeight() / 2) + this.radius * Math.sin(this.angle));
this.angle += this.step;
int deltaX = view.getMeasuredWidth();
int deltaY = view.getMeasuredHeight();
int deltaImageX = this.imageButton.getMeasuredWidth() / 2;
int deltaImageY = this.imageButton.getMeasuredHeight() / 2;
int xToDraw = ((x - deltaX) - deltaImageX);
int yToDraw = ((y - deltaY) - deltaImageY);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParams.addRule(RelativeLayout.ABOVE, CENTER_ID);
layoutParams.addRule(RelativeLayout.RIGHT_OF, CENTER_ID);
layoutParams.setMargins(xToDraw, 0, 0, yToDraw);
view.setLayoutParams(layoutParams);
return view;
}
#Override
public boolean onDrag(View view, DragEvent event) {
return this.onDrop.onDrop(view, event);
}
}
Unfortunately the imageview (imageViewBackgroundWave) is not aligning at the bottom. It aligns a little bit higher:
So the question is: how can I align my imageview to the bottom of the screen?
The image is exactly as high and as wide as the blue stripe. there is no
padding or white color in it. Its just the blue stripe shown in the picture above.
EDIT:
The background_wave.png:
I use this custom layout in my MenuFragment and call it with the following code:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// ... init the imagebuttons in the list of views
this.circleView = new CircularLayout(this.getActivity(), this, 250, views);
this.circleView.setOnDragListener(this);
this.circleView.setBackground(this.getResources().getDrawable(R.drawable.background));
return this.circleView;
}
You can get the ImageView to stick to the bottom by adding this line of code:
imageView.setScaleType(ScaleType.FIT_END);
The reason for the weirdness is that the ImageView bounds are calculated by the layout engine first, then the image inside the ImageView is scaled to fit the allocated area according to the scale type.
Using WRAP_CONTENT for the ImageView allocates an area based on the size of the unscaled image bitmap - even if it is larger than the screen. Your background_wave.png file is wider than the screen, so a larger area than is needed is allocated. Then afterwards when the image gets fitted inside the layout area using FIT_CENTER it gets shrunk down and centered, so you end up up with white space above and below it.
You can verify this by resizing your background_wave.png to be 1/4 the size: it should align the bottom even without the above code change.
You are setting width and height twice with RelativeLayout.LayoutParams.WRAP_CONTENT and RelativeLayout.ALIGN_PARENT_BOTTOM
Try this:
private void initView(Context context) {
RelativeLayout.LayoutParams layoutParamsView = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
this.setLayoutParams(layoutParamsView);
RelativeLayout.LayoutParams layoutParamsImageview = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
this.imageView = new ImageView(this.getContext());
this.imageView.setLayoutParams(layoutParamsImageview);
this.imageView.setImageDrawable(this.getResources().getDrawable(R.drawable.background_wave));
this.addView(this.imageView);
}
I also recommend you to use visual designer with XML to test layout's rules and parameters, then, if you need it, you can set that rules in code to get the same result.

Repeating a custom view in a layout

I'm just starting out with custom views. I'd like to create a view and have it repeat n times down a layout.
With the following code, the custom view is not repeating. What's more, if I insert it before the label and the button, then they are not rendered. However, if I insert the custom view after the other two controls, then they are shown.
I've played around with onLayout etc however have had no success.
Can someone please point me in the right direction?
Cheers.
public class ThreeRects : View
{
Paint _boxPaint;
Paint _boxPaint2;
Paint _boxPaint3;
public ThreeRects (Context context): base(context)
{
this._boxPaint = new Paint (PaintFlags.AntiAlias);
this._boxPaint.SetStyle (Paint.Style.Fill);
_boxPaint.Color = Color.Aqua;
this._boxPaint2 = new Paint (PaintFlags.AntiAlias);
this._boxPaint2.SetStyle (Paint.Style.Fill);
_boxPaint2.Color = Color.Red;
this._boxPaint3 = new Paint (PaintFlags.AntiAlias);
this._boxPaint3.SetStyle (Paint.Style.Fill);
_boxPaint3.Color = Color.Blue;
}
protected override void OnDraw (Android.Graphics.Canvas canvas)
{
var rect = new RectF (0, 0, 50, 50);
var rect2 = new RectF (50, 50, 100, 100);
var rect3 = new RectF (100, 100, 150, 150);
canvas.DrawRect (rect, this._boxPaint);
canvas.DrawRect (rect2, this._boxPaint2);
canvas.DrawRect (rect3, this._boxPaint3);
base.OnDraw (canvas);
}
}
[Activity (Label = "FertPinAndroid", MainLauncher = true)]
public class MainActivity : Activity
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate(bundle);
var layout = new LinearLayout (this);
layout.Orientation = Orientation.Vertical;
var aLabel = new TextView (this);
aLabel.Text = "Hello World";
var aButton = new Button (this);
aButton.Text = "Say Hello";
aButton.Click += (sender, e) => {
aLabel.Text = "Hello from the button";
};
layout.AddView (new ThreeRects (this));
layout.AddView (aLabel);
layout.AddView (aButton);
layout.AddView (new ThreeRects (this));
layout.AddView (new ThreeRects (this));
SetContentView (layout);
}
}
You didn't specify layout params for the LinearLayout or the sub-views. I would put layout.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT); and for each of the ThreeRects instances use the same. You also need to override onMeasure(int,int) in the ThreeRects class so Android can figure out how to include it in a layout. Maybe they are getting drawn on top of each other because you didn't override that method.

Android ViewGroup: what should I do in the onLayout() override?

When extending an Android ViewGroup class, what is the purpose of the onLayout() override? I'm making a custom control in Android but for some reason the content (child View objects) isn't displaying. My approach was to extend the ViewGroup class, adding child-Views via the addView() method of ViewGroup. Then, in my main activity, I have the following code:
ChannelController myCC = new ChannelController(this);
setContentView(myCC);
ChannelController is the name of my custom class that extends ViewGroup. I must be doing something wrong because nothing is shown on the screen.
I understand that I must override and implement the onLayout() method, but with what? I know there's an entire page dedicated to this on the dev.android site, but it didn't help me much, mostly because I'm a newbie I guess. Any insight would be appreciated.
For reference, my ViewGroup extension looks like below:
public class ChannelController extends ViewGroup {
final String TAG = "JAL";
public ChannelController(Context c)
{
super(c);
init(c);
}
public ChannelController(Context c, AttributeSet attibset)
{
super(c);
init(c);
}
public ChannelController(Context c, AttributeSet attribset, int defStyle)
{
super(c);
init(c);
}
public void init(Context c)
{
//RelativeLayout wrap = new RelativeLayout(c);
RelativeLayout.LayoutParams wrapLP = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
RelativeLayout r1 = new RelativeLayout(c);
RelativeLayout.LayoutParams r1LP = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
RelativeLayout r2 = new RelativeLayout(c);
RelativeLayout.LayoutParams r2LP = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
TextView t = new TextView(c);
RelativeLayout.LayoutParams tlp = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
Button m = new Button(c);
RelativeLayout.LayoutParams mlp = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
Button s = new Button(c);
RelativeLayout.LayoutParams slp = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
SeekBar f = new SeekBar(c);
RelativeLayout.LayoutParams flp = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
t.setId(1);
m.setId(2);
s.setId(3);
f.setId(4);
r1.setId(5);
r2.setId(6);
t.setText("CHANNELNAME");
t.setTextColor(Color.BLACK);
tlp.setMargins(30, 0, 0, 0);
tlp.addRule(RelativeLayout.LEFT_OF, m.getId());
tlp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
tlp.addRule(RelativeLayout.CENTER_VERTICAL);
tlp.addRule(RelativeLayout.CENTER_HORIZONTAL);
m.setText("M");
m.setBackgroundColor(Color.rgb(237, 155, 31));
m.setTextColor(Color.WHITE);
mlp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
mlp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
m.setTextSize(10);
flp.addRule(RelativeLayout.LEFT_OF, s.getId());
flp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
flp.addRule(RelativeLayout.CENTER_VERTICAL);
s.setText("S");
s.setTextSize(10);
s.setBackgroundColor(Color.rgb(192, 48, 46));
s.setTextColor(Color.WHITE);
slp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
slp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
r1.addView(t, tlp);
r1.addView(m, mlp);
r2.addView(f, flp);
r2.addView(s, slp);
r1.setBackgroundColor(Color.rgb(233, 242, 251));
r2.setBackgroundColor(Color.rgb(233, 242, 251));
r1LP.addRule(RelativeLayout.ALIGN_PARENT_TOP);
r2LP.addRule(RelativeLayout.BELOW, r1.getId());
this.addView(r1, r1LP);
this.addView(r2, r2LP);
this.setLayoutParams(wrapLP);
//this.addView(wrap);
Log.i(TAG, "ChannelController constructor was called");
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
//super.onLayout(changed, l, t, r, b);
}
}
What do I need to do in the onLayout method override?
In onLayout you need to call layout method on each child of this ViewGroup and provide desired position (relatively to parent) for them. You can check source code of FrameLayout (one of the simpliest subclasses of ViewGroup) to find out how it works.
Although, if you don't need any "special" layouting, you have other options:
Extend some another subclass of ViewGroup instead (FrameLayout for example)
Use LayoutInflater if you just need your control to look exactly as in XML (which, I think, is exactly your case)
Actually it helps in positioning children of a view group. following code may help
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
MarginLayoutParams layoutParams = (MarginLayoutParams) icon.getLayoutParams();
// Figure out the x-coordinate and y-coordinate of the icon.
int x = getPaddingLeft() + layoutParams.leftMargin;
int y = getPaddingTop() + layoutParams.topMargin;
// Layout the icon.
icon.layout(x, y, x + icon.getMeasuredWidth(), y + icon.getMeasuredHeight());
// Calculate the x-coordinate of the title: icon's right coordinate +
// the icon's right margin.
x += icon.getMeasuredWidth() + layoutParams.rightMargin;
// Add in the title's left margin.
layoutParams = (MarginLayoutParams) titleView.getLayoutParams();
x += layoutParams.leftMargin;
// Calculate the y-coordinate of the title: this ViewGroup's top padding +
// the title's top margin
y = getPaddingTop() + layoutParams.topMargin;
// Layout the title.
titleView.layout(x, y, x + titleView.getMeasuredWidth(), y + titleView.getMeasuredHeight());
// The subtitle has the same x-coordinate as the title. So no more calculating there.
// Calculate the y-coordinate of the subtitle: the title's bottom coordinate +
// the title's bottom margin.
...
you can find more detail about custom views here
custom views

Custom Views only showing up once

I've made a very simple customView, a gray rectangle with an arbitrary amount of red markings inside the rectangle marked by percentages.
public class DemoView extends View {
private ShapeDrawable mDrawable;
private ArrayList<ShapeDrawable> mMarks;
public DemoView(Context context, int[] marks) {
super(context);
int x = 0;
int y = 0;
int width = 100;
int height = 10;
// Timeline Initially empty
mDrawable = new ShapeDrawable(new RectShape());
mDrawable.getPaint().setColor(Color.GRAY);
mDrawable.setBounds(x, y, x + width, y + height);
// Add marks
if (marks != null && marks.length % 2 == 0) {
mMarks = new ArrayList<ShapeDrawable>(marks.length / 2);
ShapeDrawable mark;
for (int i = 1; i < marks.length; i = i + 2) {
mark = new ShapeDrawable(new RectShape());
mark.getPaint().setColor(Color.RED);
mark.setBounds(x + marks[i - 1], y, x + marks[i], y + height);
mMarks.add(mark);
}
}
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mDrawable.draw(canvas);
if (mMarks != null)
for (ShapeDrawable mark : mMarks)
mark.draw(canvas);
}
}
However I can't figure out how to make use of the view. Each time I try to add more than one of the view in a linearlayout or relativelayout, I only see one of the views.
XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/llayout"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello"
/>
</LinearLayout>
Layout code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout ll = (LinearLayout) findViewById(R.id.llayout);
demoview = new DemoView(this, new int[]{10,15,35,60});
demoview.setId(ID_NUM++);
ll.addView(demoview);
demoview2 = new DemoView(this, new int[]{0,1,3,6});
demoview2.setId(ID_NUM++);
ll.addView(demoview2);
demoview3 = new DemoView(this, new int[]{25,60});
demoview3.setId(ID_NUM++);
ll.addView(demoview3);
demoview4 = new DemoView(this, new int[]{15,60});
demoview4.setId(ID_NUM++);
ll.addView(demoview4);
}
Results in:
Is this the wrong route to take? Am I missing some obvious key to using this view multiple times? If this is not the correct route is there some other method to making a custom shape? Perhaps extending rectShape?
Following Mibollma's advice, I watched the video above, a video from Google I/O 2009 about speeding up your UI.
The information is most definitely still applicable two years later. Not only was I able to speed up all of my ListViews through the use of ViewHolder, I was able to find the answer to my question.
When creating a custom view, two methods must be overriden, the first is listed above: onDraw.
The missing method? onMeasure(). More information can be found here.

Categories

Resources