#android #canvas #drawable
#Android #холст #возможность рисования
Вопрос:
Моя активность имеет setContentView с классом SurfaceView. Теперь я безуспешно пытаюсь нарисовать векторную графику на этом холсте SurfaceView, я вижу только черный экран.
Итак, у меня есть немного векторной графики в XML-файле — R.drawable.battery. Он правильно отображается в окне предварительного просмотра Android Studio.
public class BoardActivity extends Activity {
MySurfaceView mySurface; // My surfaceview class
Drawable vd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mySurface = new MySurfaceView(this);
vd = ContextCompat.getDrawable(getApplicationContext(), R.drawable.battery);
setContentView(mySurface);
public class MySurfaceView extends SurfaceView implements Runnable{
Thread t;
SurfaceHolder holder;
boolean isItOK = false;
public MySurfaceView(Context context) {
super(context);
holder = getHolder();
resume();
}
@Override
public void run() {
while(isItOK==true) {
if(!holder.getSurface().isValid()) {
continue;
}
Canvas canvas = holder.lockCanvas();
canvas .drawARGB(80, 188, 230, 227 );
vd.draw(canvas); // draw nothing!
// canvas.drawRect(... works perfect! The issue is only with vd.draw(canvas);
holder.unlockCanvasAndPost(c);
}
public void pause() {
isItOK = false;
while(true) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
t = null;
}
public void resume(){
isItOK = true; //Starting drawing
t = new Thread(this);
t.start();
}
}
Ответ №1:
Я новичок в Android, поэтому я действительно не знаю, является ли то, что я покажу вам, хорошей практикой, но вот она:
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.SurfaceView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Drawable d = getResources().getDrawable(R.drawable.battery, null);
final SurfaceView view = new SurfaceView(this) {
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
d.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
d.draw(canvas);
}
};
view.setBackgroundColor(Color.WHITE);
setContentView(view);
}
}
Этот код работает для меня.
Важно: вы установили цвет фона на белый? Если нет, то я думаю, что не нужно, и если ваш холст будет отображаться правильно в дизайн вкладки в Андроид-студии, то я думаю, что это должно работать в вашем приложении тоже.
В качестве альтернативы (и может быть лучше) вы можете рассмотреть ImageView
, а также добавить ее в файл ресурсов макета. Например, основной код действия может стать:
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
а затем в res/layout/activity_main.xml
поместить:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@ id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/battery"
android:contentDescription="@string/batteryDesc" />
</androidx.constraintlayout.widget.ConstraintLayout>
Не забудьте добавить batteryDesc
именованную константу в res/values/strings.xml
.
Комментарии:
1. Привет, gthanop! Спасибо, это работает, но это статично. Но у меня есть SurfaceView в отдельном потоке и запущен метод run () для обновления экрана со скоростью обновления 60 кадров в секунду (это классический игровой шаблон). Таким образом, d.draw (canvas) не работает.
2. Привет. Я думаю, вам следует опубликовать весь свой код в вашем вопросе (в основном код вашей активности и
Thread
), чтобы другие могли понять, что вы ищете. Почему это неd.draw(canvas);
не работает? Создавали ли вы подкласс,SurfaceView
чтобы переопределить егоonDraw
и нарисовать там изображение? Что еще нарисовано наSurfaceView
? На все эти вопросы можно получить ответы, если вы предоставите как можно больше кода вашего приложения внутри вашего вопроса. Работает ли ваша программа для рисования? Опубликуйте это также в вопросе. Аннулирование представления каждые 16 мс не означает, что вы не можете переопределитьSurfaceView.onDraw
для drawable3. переопределение onDraw () также мне не помогло. Я нашел решение в преобразовании моего изображения в растровое изображение с помощью bitmap = Bitmap.CreateBitmap (векторное изображение.getIntrinsicWidth(), векторное изображение.getIntrinsicHeight (), Bitmap.Config. ARGB_8888); canvas = new Canvas(bitmap); VectorImage.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); VectorImage.draw(canvas); и затем применяем canvas.drawBitmap(bitmap, 0, 0, null); в методе run() SurfaceView. Это действительно странный обходной путь.
4. Если вы нашли ответ самостоятельно, то вы можете ответить на свой собственный вопрос и принять его по истечении определенного количества времени. Если вам нужна дополнительная помощь, вы можете следовать инструкциям, которые я вам уже дал (т. Е. Опубликовать код ваших классов в вопросе), а также ответить на мои вопросы, если это возможно. Лично я не думаю, что есть необходимость в этом обходном пути, но это всего лишь мое мнение. Если вы опубликуете свой код в своем вопросе, то мы могли бы предложить решение вашей проблемы, но я не думаю, что вы сможете получить лучшую помощь, чем с помощью кода, опубликованного в вашем вопросе. Обходной путь.
5. Я обновил первоначальный вопрос более или менее полной настройкой кода! Пожалуйста, проверьте это.