Изображения, загруженные с помощью BitmapRegionDecoder, подходят для симулятора, но слишком велики для устройства.
В простом приложении для игры в слова я загружаю 26 буквенных изображений с полосы PNG-изображения со следующим кодом:
private static final CharacterIterator ABC =
new StringCharacterIterator("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
private static HashMap<Character, Bitmap> sImages =
new HashMap<Character, Bitmap>();
BitmapRegionDecoder decoder = null;
InputStream is = sContext.getResources()
.openRawResource(R.drawable.big_english);
try {
decoder = BitmapRegionDecoder.newInstance(is, false);
} catch (IOException ex) {
}
int h = decoder.getHeight();
Rect r = new Rect(0, 0, h, h);
for (char c = ABC.first();
c != CharacterIterator.DONE;
c = ABC.next(), r.offset(h, 0)) {
Bitmap bmp = decoder.decodeRegion(r, null);
sImages.put(c, bmp);
}
Это хорошо работает в эмуляторе Android:
Но на реальном устройстве Moto G буквы слишком большие (может быть, в 1,5 раза? Когда я печатаю sContext.getResources().getDisplayMetrics().density
Я почему-то получаю 2.0)
В то же время желтый квадратный фон мозаичного изображения отображается правильно.
Все ( big_tile.png и big_english.png и game_board.png) являются PNG-изображениями - так в чем же разница?
Почему так происходит и как это исправить пожалуйста?
Должен ли я использовать inDensity
или любые другие BitmapFactory.Options?
Или это из-за моего getResources().openRawResource()
позвонить - но что использовать вместо этого?
2 ответа
У меня тоже такая же проблема с изображением, андроид устройства пришли со многими разрешениями экрана. Вам нужно будет либо поместить много изображений в вашу папку для рисования, либо задать набор правил для ширины и высоты изображения для каждого разрешения экрана.
for example:
if screen_resolution = 4 inch
int img_height = 200
int img_width = 200
else if screen_resolution = 5 inch
int img_height = 300
int img_width = 300
,, и так далее, надеюсь, это может помочь вам, как.
Вот часть моего кода (я использую imageview, а не растровое изображение, извините):
int ширина, высота;
//calculate device screen
DisplayMetrics metrics=new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
float height=metrics.heightPixels/metrics.xdpi;
float width=metrics.widthPixels/metrics.ydpi;
float inchscreen = FloatMath.sqrt(height*height+width*width);
if (inchscreen > 4.1000)
{
//set image height for device above 4.1 inch screen
height = 400;
width = 400
}
else {
//set image height for device below 4.1 inch screen
height = 280;
width = 280
}
if (imgfile != null) {
int imageResource = getResources().getIdentifier(uri, null,
getPackageName());
Drawable image = getResources().getDrawable(imageResource);
imageview.setImageDrawable(image);
imageview.getLayoutParams().height = h_display;
imageview.getLayoutParams().width = h_display;
}
Я поделюсь своим собственным решением здесь.
Проблема была в том, что желтый фон для моих буквенных плиток Drawable
и передний план является Bitmap
(читать с помощью BitmapRegionDecoder
из PNG-полосы).
По какой-то странной причине я до сих пор не понимаю - их размеры отличаются на некоторых устройствах Android.
(1) Так что мой самый простой обходной путь - это масштабировать Bitmap
(передний план с буквой) в пределы Drawable
(желтый квадратный фон) каждый раз, когда рисуется тиснение письма:
private Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
public void draw(Canvas canvas) {
canvas.save();
canvas.translate(left, top);
mImage.draw(canvas);
Bitmap bmp = getImages().get(mLetter);
canvas.drawBitmap(bmp, null, mImage.getBounds(), mPaint);
canvas.restore();
}
(2) Мой более сложный обходной путь - это масштабирование Bitmap
только один раз - сразу после того, как я прочитал это с BitmapRegionDecoder
и прежде чем я сохраню его в HashMap:
private static final CharacterIterator ABC =
new StringCharacterIterator("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
private static HashMap<Character, Bitmap> sBitmaps =
new HashMap<Character, Bitmap>();
try {
InputStream is = context.getResources().openRawResource(EN);
BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false);
int h = decoder.getHeight();
Rect r = new Rect(0, 0, h, h);
for (char c = ABC.first();
c != CharacterIterator.DONE;
c = ABC.next(), r.offset(h, 0)) {
Bitmap unscaled = decoder.decodeRegion(r, null);
Bitmap scaled = Bitmap.createScaledBitmap(unscaled, (int) (SCALE * width), (int) (SCALE * height), true);
sBitmaps.put(c, scaled);
}
} catch (IOException ex) {
}
(3) Оба метода работали, но на старом устройстве Google Nexus One я почему-то не мог видеть передний план. В этот момент я потерял самообладание, перестал использовать BitmapRegionDecoder
и просто разделить PNG-полосу с помощью ImageMagick (команда convert square.png -crop 40x40 square_%d.png
). Теперь мое приложение использует Drawable
как для переднего плана, так и для фона буквенных плиток и работает на всех устройствах, начиная с SDK уровня 8:
private static final String SQUARE = "square_";
private static final char[] LETTERS = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
private static HashMap<Character, Drawable> sLetters =
new HashMap<Character, Drawable>();
for (int i = 0; i < LETTERS.length; i++) {
char c = LETTERS[i];
int id = context.getResources().getIdentifier(PREFIX + i, "drawable", context.getPackageName());
Drawable d = context.getResources().getDrawable(id);
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
sLetters.put(c, d);
}