Android how can you add a custom view programmatically without affecting rest of layout
I'm creating a guitar app. It has an relative layout holding an image view to display the guitar fretboard and at the bottom a linear layout holding some Buttons. The issue occurs when I want to highlight the note on the fretboard. I've created a customer drawable view and when I add it to the relative layout holding an image view, it highlights, BUT the linear layout holding some buttons disappears. Why? What do I need to do?
Layout
<?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">
<!-- Top line -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_black"
android:orientation="horizontal"
android:id="@+id/appHeader">
<TextView android:id="@+id/headerText" android:text="@string/app_name"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textColor="@android:color/white" android:textSize="17dip" android:textStyle="bold"
android:gravity="center" android:paddingTop="2dip" android:paddingBottom="2dip"
android:layout_weight="1" />
<SeekBar android:layout_height="wrap_content"
android:id="@+id/seek_bar"
android:layout_width="300dip"
android:paddingTop="2dip"
android:paddingBottom="2dip"
android:paddingRight="4dip"
android:saveEnabled="true"
android:max="100"
android:progress="50">
</SeekBar>
</LinearLayout>
<!-- Middle Guitar to scroll left-right-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fretboard_layout"
android:orientation="horizontal"
android:layout_width="2040dip"
android:layout_height="wrap_content"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/guitar_fretboard"
android:scaleType="center"
android:background="@drawable/bg_black"
android:src="@drawable/mina_fretboard_1951x218"
/>
</RelativeLayout>
<!-- Bottom Buttons-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_black"
android:gravity="center_horizontal|center_vertical"
android:orientation="horizontal">
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="2dip"
android:orientation="horizontal">
<Button
android:id="@+id/choose_tune_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTop="@drawable/music"
android:minWidth="96dip"
android:text="@string/choose_tune"
/>
<Button
android:id="@+id/play_tune_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTop="@drawable/play_stop"
android:minWidth="96dip"
android:text="@string/play_tune"
/>
<Button
android:id="@+id/check_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="96dip"
android:drawableTop="@drawable/check"
android:text="@string/check_notes"
/>
<Button
android:id="@+id/note_count_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="96dip"
android:drawableTop="@drawable/number"
android:text="@string/note_count"
/>
<Button开发者_如何学编程
android:id="@+id/options_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="96dip"
android:drawableTop="@drawable/options_32"
android:text="@string/options"
/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
CustomDrawableView class for highlighting
package com.veitch.learntomaster.grp.ui.activities;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.view.View;
public class CustomDrawableView extends View {
private ShapeDrawable mDrawable;
private int x;
private int y;
private int drawableWidth;
private int drawableHeight;
public CustomDrawableView(Context context, int x, int y, int drawableWidth, int drawableHeight) {
super(context);
this.x = x;
this.y = y;
this.drawableWidth = 30;
this.drawableHeight = 15;
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xff74AC23);//Green
mDrawable.setAlpha(128);//50% opacity?
mDrawable.setBounds(this.x, this.y, this.x + this.drawableWidth, this.y + this.drawableHeight);
}
protected void onDraw(Canvas canvas) {
mDrawable.draw(canvas);
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public void setDrawableWidth(int drawableWidth) {
this.drawableWidth = drawableWidth;
}
public int getDrawableWidth() {
return drawableWidth;
}
public void setDrawableHeight(int drawableHeight) {
this.drawableHeight = drawableHeight;
}
public int getDrawableHeight() {
return drawableHeight;
}
}
Main Activity, calling the CustomerDrawableView
userPlayedHighlightView = new CustomDrawableView(this,x,y,HIGHLIGHT_WIDTH,HIGHLIGHT_HEIGHT);
fretboardLayout.addView(userPlayedHighlightView);
I would use another approach for your problem. I would built a FredboardView
which is capable of drawing a highlighted note in its onDraw
method. This View could be added in your layout xml. If you want to highglight a note the view should have a method to do this like setHihglightedNote(note)
and you would not have to add something to the layout everytime the user does something.
EDIT:
Example of a custom view which draws some drawables according to a position.
public class PositionIndicator extends View {
private static final int OFFSET = 2;
private Drawable on, off;
private int width, height;
private int size = 5;
private int position = 0;
private Paint paint;
public PositionIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
// init
on = context.getResources().getDrawable(R.drawable.dot_green);
off = context.getResources().getDrawable(R.drawable.dot_grey);
paint = new Paint();
paint.setARGB(0, 0, 0, 0);
}
/**
* Set size of indicator.
* @param size Size.
*/
public void setSize(int size) {
if(size >= 0)
this.size = size;
this.invalidate();
}
/**
* Set position of indicator.
* @param position Position.
*/
public void setPosition(int position) {
if(position >= 0 && position <= size)
this.position = position;
this.invalidate();
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch(msg.what) {
case C.POSITION_CHANGED:
setPosition(msg.arg1);
break;
}
}
};
public Handler getHandler() {
return handler;
}
/**
* {@inheritDoc}
*/
@Override
public void onDraw(Canvas canvas) {
// draw transparent rectangle to clean area
canvas.drawRect(0, 0, this.getWidth(), this.getHeight(), paint);
for(int i = 0; i < size; i++) {
// draw current
if(i+1 == position) {
on.setBounds(i*width+i*OFFSET, 0, i*width+i*OFFSET+width, height);
on.draw(canvas);
// draw others
} else {
off.setBounds(i*width+i*OFFSET, 0, i*width+i*OFFSET+width, height);
off.draw(canvas);
}
}
}
/**
* {@inheritDoc}
*/
@Override
protected void onMeasure(int width, int height) {
super.onMeasure(width, height);
setMeasuredDimension(this.getMeasuredWidth(), this.getMeasuredHeight());
this.width = (this.getMeasuredWidth() - ((size-1) * OFFSET)) / size;
this.height = this.getMeasuredHeight();
}
}
精彩评论