Как программно создать или изменить drawable из линий разных цветов
Я должен нарисовать линию 3dp, чтобы представить завершение уровня в игре викторины.
эта линия должна иметь 2 цвета. Например, если пользователь завершил 40% уровня, линия будет Красной для первых 40% линии, а остальные 60% будут серыми.
мне удалось сделать это с помощью drawable:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="line" >
<size android:height="3dp" android:width="40dp"/>
<stroke
android:width="1dp"
android:color="#FFFC10" />
</shape>
</item>
<item android:left="40dp">
<shape android:shape="line" >
<size android:height="3dp" android:width="60dp" />
<stroke
android:width="1dp"
android:color="#DDDDDD" />
</shape>
</item>
</layer-list>
и затем я отображаю его с помощью ImageView:
<ImageView
android:id="@+id/row_completion_bar"
android:src="@drawable/completion_bar"
android:layout_width="100dp"
android:layout_height="3dp" />
... но теперь я, конечно, должен иметь возможность изменить этот 40%/60% рацион в зависимости от завершения пользователя actuel.
первый вопрос: каков наилучший наиболее эффективный способ сделать это ? Изменить drawable во время выполнения ? или создать новый drawable во время выполнения в Java ?
второй вопрос: как это сделать ? Я попробовал оба способа (воссоздать этот drawable в коде java / изменить XML drawable во время выполнения) и не удалось : - (
любая помощь будет высоко оценили.
4 ответов
Так что это пользовательский Drawable вы можете использовать:
class LineDrawable extends Drawable {
private Paint mPaint;
public LineDrawable() {
mPaint = new Paint();
mPaint.setStrokeWidth(3);
}
@Override
public void draw(Canvas canvas) {
int lvl = getLevel();
Rect b = getBounds();
float x = b.width() * lvl / 10000.0f;
float y = (b.height() - mPaint.getStrokeWidth()) / 2;
mPaint.setColor(0xffff0000);
canvas.drawLine(0, y, x, y, mPaint);
mPaint.setColor(0xff00ff00);
canvas.drawLine(x, y, b.width(), y, mPaint);
}
@Override
protected boolean onLevelChange(int level) {
invalidateSelf();
return true;
}
@Override
public void setAlpha(int alpha) {
}
@Override
public void setColorFilter(ColorFilter cf) {
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
и тестовый код:
View v = new View(this);
final LineDrawable d = new LineDrawable();
d.setLevel(4000);
v.setBackgroundDrawable(d);
setContentView(v);
OnTouchListener l = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int lvl = (int) (10000 * event.getX() / v.getWidth());
d.setLevel(lvl);
return true;
}
};
v.setOnTouchListener(l);
как использовать прогресс бар? Стиль маркеров done и to-do можно установить программно или с помощью xml-файлов. Ваш код будет более читабельным/ремонтопригодным, потому что вы будете использовать правильный виджет для работы. Ваш макет будет содержать:
<ProgressBar
android:id="@+id/progressBar"
android:layout_height="3dip"
android:layout_width="match_parent"
android:progressDrawable="@drawable/progress_bar" />
вы можете обновить строку из кода, используя например:
ProgressBar bar = (ProgressBar)findViewById(R.id.progressBar);
bar.setProgress(40);
этот пример переопределяет стиль бара (как указано атрибутом progressDrawable), используя res/drawable/progress_bar.XML файл - содержание ниже. У этого есть дополнительная приятность, такая как градиентное затенение и закругленные углы; отрегулируйте, как вы считаете нужным:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@android:id/background">
<shape>
<corners android:radius="5dip" />
<gradient
android:angle="270"
android:centerColor="#ff5a5d5a"
android:centerY="0.5"
android:endColor="#ff747674"
android:startColor="#ff9d9e9d" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="5dip" />
<gradient
android:angle="0"
android:endColor="#ff009900"
android:startColor="#ff000099" />
</shape>
</clip>
</item>
</layer-list>
кредит http://www.tiemenschut.com/how-to-customize-android-progress-bars/, что дает гораздо больше информации о том, как настроить индикаторы прогресса.
Я нашел способ сделать это. Не знаю, самый ли это эффективный способ, но вот он:
я использовал RelativeLayout для суперпозиции изображений с цветом фона.
в макете.XML-код:
<RelativeLayout style="@style/CompletionBar">
<ImageView
android:id="@+id/row_completion_bar_0"
style="@style/CompletionBar0" />
<ImageView
android:id="@+id/row_completion_bar_1"
style="@style/CompletionBar1" />
</RelativeLayout>
в стилях.XML-код:
<!-- Completion Bar (Relative Layout) -->
<style name="CompletionBar">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
</style>
<!-- Completion Bar 0 (ImageView) -->
<style name="CompletionBar0">
<item name="android:layout_width">100dp</item>
<item name="android:layout_height">2dp</item>
<item name="android:background">#CCCCCC</item>
</style>
<!-- Completion Bar 1 (ImageView) -->
<style name="CompletionBar1">
<item name="android:layout_width">40dp</item>
<item name="android:layout_height">2dp</item>
<item name="android:background">#555555</item>
</style>
в файле java:
ImageView cb1 = (ImageView)row.findViewById(R.id.row_completion_bar_1);
cb1.getLayoutParams().width = 40; /* Value in pixels, must convert to dp */
этот фрагмент будет работать для всех api
используйте этот:
Drawable drawable = editText.getBackground();
drawable.setColorFilter(editTextColor, PorterDuff.Mode.SRC_ATOP);
if(Build.VERSION.SDK_INT > 16) {
editText.setBackground(drawable);
}else{
editText.setBackgroundDrawable(drawable);
}