5

У меня есть активность, которая имеет ImageView, определенный внутри HorizontalScrollView. Источник изображения представляет собой файл с 9 патчами, который ограничен, чтобы растянуть только правый край, чтобы заполнить экран. Я реализовал функцию простого масштабирования, которая позволяет пользователю дважды увеличивать и уменьшать масштаб, изменяя размер растрового изображения и назначая новое растровое изображение для представления. Моя текущая проблема заключается в том, что при удвоении нажатия, чтобы уменьшить масштаб, 9-патч не применяется, когда я назначаю новое изменение размера растрового изображения в представление. Другими словами, вместо растяжения только правого края, как определено в файле с 9 патчами, он растягивал все изображение.Как программно повторно применить 9-образное изображение к ImageView?

Вот мой XML:

<HorizontalScrollView 
      android:id="@+id/hScroll" 
      android:fillViewport="true" 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      android:fadingEdge="none" > 

      <RelativeLayout 
       android:id="@+id/rlayoutScrollMap" 
       android:layout_width="fill_parent" 
       android:layout_height="fill_parent" > 

       <ImageView 
        android:id="@+id/imgResultMap" 
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent" 
        android:scaleType="fitXY" 
        android:src="@drawable/map_base"/> 

      </RelativeLayout> 
     </horizontalScrollView> 

Вот соответствующая часть моего кода, внутри onDoubleTap() вызова:

public boolean onDoubleTap(MotionEvent e) 
       { 
        if (zoom == 1) { 
         zoom = 2; // zoom out 
        } else { 
         zoom = 1; // zoom in 
        } 
        Bitmap image = BitmapFactory.decodeResource(getResources(),R.drawable.map_base);    
        Bitmap bmp = Bitmap.createScaledBitmap(image, image.getWidth() * zoom, image.getHeight() * zoom, false); 
        ImageView imgResultMap = (ImageView)findViewById(R.id.imgResultMap); 
        imgResultMap.setImageBitmap(bmp); 

        return false; 
       } 

EDIT: После выполнения некоторых исследований, я имею это выяснилось. Вместо того, чтобы просто манипулировать растровым изображением, мне нужно также включить фрагмент 9-патча, который не является частью изображения растрового изображения, для повторной сборки нового 9-патча. См пример кода ниже:

... 
else { 
     // Zoom out 
     zoom = 1; 
     Bitmap mapBitmapScaled = mapBitmap; 
     // Load the 9-patch data chunk and apply to the view 
     byte[] chunk = mapBitmap.getNinePatchChunk(); 
     NinePatchDrawable mapNinePatch = new NinePatchDrawable(getResources(), 
      mapBitmapScaled, chunk, new Rect(), null); 
     imgResultMap.setImageDrawable(mapNinePatch); 
} 

    .... 

ответ

8

EDIT: После выполнения некоторых исследований, я понял. Вместо того, чтобы просто манипулировать растровым изображением, мне нужно также включить фрагмент 9-патча, который не является частью изображения растрового изображения, для повторной сборки нового 9-патча. Смотрите пример кода ниже:

... 
else { 
     // Zoom out 
     zoom = 1; 
     Bitmap mapBitmapScaled = mapBitmap; 
     // Load the 9-patch data chunk and apply to the view 
     byte[] chunk = mapBitmap.getNinePatchChunk(); 
     NinePatchDrawable mapNinePatch = new NinePatchDrawable(getResources(), 
      mapBitmapScaled, chunk, new Rect(), null); 
     imgResultMap.setImageDrawable(mapNinePatch); 
} 

    .... 

EDIT # 2: Для тех, кто смотрит на мое решение здесь, а также взглянуть на предложения Кая ниже относительно управления памятью. Очень полезная информация.

+0

Отлично, мне нужно было сделать некоторые манипуляции на ресурсе 9patch, и без этого фрагмента кода я действительно не знал, с чего начать! Благодаря! –

+0

Попробуйте использовать setImageResource (9patchResourceID) вместо setImageBitmap или setImageBackground, и он работает :) – Shilpi

0

Переместить это: ImageView imgResultMap = (ImageView)findViewById(R.id.imgResultMap); к глобальным intialized в методе OnCreate. В противном случае устройство должно искать представление и находить его каждый раз, когда он прослушивается.

и попробуйте позвонить imgResultMap.invalidate();, прежде чем вернуться из метода onDoubleTap (http://developer.android.com/reference/android/view/View.html#invalidate())

+0

Пожалуйста, смотрите мое собственное решение выше. – Kenny

+0

@ Kenny вы должны отправить свое решение в качестве ответа, а затем пометить его принятым. – you786

+0

хорошая идея. только что отправил и примет ответ завтра. – Kenny

1

Почему вы просто не включают два различных масштабируемые изображения и переключаться между ними с помощью imgResultMap.setImageResource(resId) при масштабировании? Также обратите внимание, что вы загружаете &, создавая растровые изображения в UIThread, что не является хорошим способом обеспечить плавное пользовательское восприятие, по крайней мере, предварительно загружать растровое изображение только один раз во время onCreate() и кэширования.

+0

Это хороший момент. Тем не менее, у меня есть около 35 элементов, которые имеют масштабированные версии, созданные аналогично тому, что я показал выше, и я делаю сборку мусора сразу после создания каждой масштабированной версии (используя v.recycle()). Я беспокоюсь, что когда я создаю масштабированную версию во время onCreate(), есть ли вероятность, что я получу ошибку OOM прямо перед тем, потому что ей по существу нужно хранить обе версии в памяти? – Kenny

+0

Вы должны иметь возможность рассчитать объем памяти, поднятый на изображение, с помощью img_width * img_height * 4, чтобы узнать, сколько памяти потребуется этим 35 элементам, а затем решить, имеет ли смысл загружать обе версии в память однажды. – Kai

+0

Для загрузки всех этих изображений в действие требуется ~ 2,4 МБ, поэтому, возможно, это нормально, чтобы создать их спереди. Когда я выхожу из этой операции, будет ли автоматически выполняться сбор мусора, чтобы память была освобождена для других моих действий? Кроме того, остается ли реалистично предположить, что текущие телефоны и планшеты позволят только 24 Мбайт памяти кучи для каждого приложения? Я помню, когда тестировал одну из моих других действий в приложении в эмуляторе только с кучей 24 МБ, я получил OOM, и мне нужно увеличить размер кучи, чтобы продолжить тестирование. – Kenny

0

9-патч-изображения, похоже, работают только в том случае, если они установлены в качестве фонового изображения View. Итак:

  • вместо android:src установите android:background в макете XML и
  • вызов setBackgroundResource() когда вы хотите изменить изображение.

Вы также можете использовать обычную View вместо ImageView, если хотите; это не имеет большого значения.

0

Также другое решение установить изображение программно как ImageResource и установить scaleType

imageView.setImageResource(R.drawable.favorite_driver_icon); 
imageView.setScaleType(ScaleType.FIT_XY); 
Смежные вопросы