Я пытаюсь создать рамку для TextView как облака. Но область содержимого не ведет себя так, как ожидалось. Что я делаю не так? Область содержимого Nine-patch не работает
ответ
У меня есть предложение, которое работает неправильно, потому что область содержимого меньше области масштабирования. Так грустно. Я переделал его, чтобы обрабатывать 9-патч вручную. Сохраняйте фотографии без .9.png. Получите битмап. Есть 9-строчный подарок. С помощью getPixels вычитается отступы и устанавливаем его в TextView. После этого вычисляем и устанавливаем LayoutParams.width и LayoutParams.height. Выглядит немного уродливо, но работает довольно быстро, и, самое главное, правильно.
private int startX=-1;
private int endX=-1;
private int contentW=-1;
private int contentH=-1;
Bitmap bmp=BitmapFactory.decodeResource(getResources(), mIconResId);
int[] pixels=new int[bmp.getWidth()*bmp.getHeight()];
bmp.getPixels(pixels, 0, bmp.getWidth(), 0, 0, bmp.getWidth(),bmp.getHeight());
for(int i=0;i<bmp.getWidth();i++){
if(startX==-1 && pixels[bmp.getWidth()*(bmp.getHeight()-1)+i]==Color.BLACK){
startX=i;
}
if(startX!=-1 && pixels[bmp.getWidth()*(bmp.getHeight()-1)+i]!=Color.BLACK){
endX=i;
break;
}
}
int startY=-1;
int endY=-1;
for(int i=0;i<bmp.getHeight();i++){
if(startY==-1 && pixels[bmp.getWidth()*(i+1)-1]==Color.BLACK){
startY=i;
}
if(startY!=-1 && pixels[bmp.getWidth()*(i+1)-1]!=Color.BLACK){
endY=i;
break;
}
}
setBackground(new BitmapDrawable(getResources(),Bitmap.createBitmap(bmp, 1, 1, bmp.getWidth()-2, bmp.getHeight()-2)));
contentW=endX-startX;
endX=bmp.getWidth()-endX;
contentH=endY-startY;
endY=bmp.getHeight()-endY;
new Handler().post(new Rannable(){
@Override
public void run() {
int w=textview.getWidth();
int h=textview.getHeight();
if(w>endX-startX){
float k=((float)w)/contentW;
startX=(int) (startX*k);
endX=(int) (endX*k);
}
if(h>endY-startY){
float k=((float)h)/contentH;
startY=(int) (startY*k);
endY=(int) (endY*k);
}
w+=startX+startX;
h+=startY+endY;
textview.setPadding(startX, startY, endX, endY);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(w,h);
textview.setLayoutParams(lp);
}
});
Вы установили хорошие значения для правой и нижней границ. Вам просто нужно установить одинаковые значения для левой и верхней границ, левая граница = правая граница и верхняя граница = нижняя граница.
Результат в draw9patch:
А вот файл 9-патч:
Для вашей информации, изображение не очень подходит для использования с форматом 9-патч.
@ahtartam, полезно ли это? – LaurentY
Нет, мне нужно искаженное изображение. Равномерно по всей ширине. И одинаково масштаб на всех высотах. – ahtartam
Итак, вы не должны использовать 9-патч, вам нужно масштабировать полное изображение (9-патч-масштаб часть изображения) и путем вычисления размера текста. – LaurentY
Я продлил/адаптировал код @ahtartam. Я не уверен, что это самый чистый способ, но он работает для меня. Если кому-то нужна помощь, просто свяжитесь со мной или спросите в комментариях!
public void setTextLayout(int orgW, int orgH,int actW,int actH,int top,int left) {
int startX = -1;
int endX = -1;
int startY = -1;
int endY = -1;
int contentW;
int contentH;
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.image);
int[] pixels = new int[orgW * orgH];
bmp.getPixels(pixels, 0, orgW, 0, 0, orgW, orgH);
for (int i = 0; i < orgW; i++) {
if (startX == -1 && pixels[orgW * (orgH - 1) + i] == Color.BLACK) {
startX = i;
}
if (startX != -1 && pixels[orgW * (orgH - 1) + i] != Color.BLACK) {
endX = i;
break;
}
}
for (int i = 0; i < orgH; i++) {
if (startY == -1 && pixels[orgW * (i + 1) - 1] == Color.BLACK) {
startY = i;
}
if (startY != -1 && pixels[orgW * (i + 1) - 1] != Color.BLACK) {
endY = i;
break;
}
}
m_marvin.setImageDrawable(new BitmapDrawable(getResources(), Bitmap.createBitmap(bmp, 1, 1, orgW - 2, orgH - 2)));
RelativeLayout.LayoutParams rp = (RelativeLayout.LayoutParams) m_marvin.getLayoutParams();
contentW=endX- startX;
contentH=endY-startY;
endX=orgW-endX;
endY=orgH-endY;
double scaleX = ((double)actW)/bmp.getWidth();
double scaleY = ((double)actH)/bmp.getHeight();
startX = (int) (startX * scaleX);
endX = (int) (endX * scaleX);
startY = (int) (startY * scaleY);
endY = (int) (endY * scaleY) ;
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams((int)(contentW*scaleX),(int)(contentH*scaleY));
layoutParams.setMargins(startX+rp.leftMargin+left, startY+rp.topMargin+top, endX+rp.rightMargin, endY+rp.bottomMargin);
layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL,RelativeLayout.TRUE);
m_text.setLayoutParams(layoutParams);
m_text.bringToFront();
}
Вместо TextView я использую SizeAwareImageView из ->https://stackoverflow.com/a/15538856/1438596
В моем случае это выглядит как this->
public class SizeAwareImageView extends ImageView {
MainActivity m_mainActivity;
public SizeAwareImageView(Context context,AttributeSet attrss){
super(context,attrss);
m_mainActivity = (MainActivity)context;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if(m_mainActivity.getTextMeasured())return;
// Get image matrix values and place them in an array
float[] f = new float[9];
getImageMatrix().getValues(f);
// Extract the scale values using the constants (if aspect ratio maintained, scaleX == scaleY)
final float scaleX = f[Matrix.MSCALE_X];
final float scaleY = f[Matrix.MSCALE_Y];
// Get the drawable (could also get the bitmap behind the drawable and getWidth/getHeight)
final Drawable d = getDrawable();
final int origW = d.getIntrinsicWidth();
final int origH = d.getIntrinsicHeight();
// Calculate the actual dimensions
final int actW = Math.round(origW * scaleX);
final int actH = Math.round(origH * scaleY);
int top = (int) (imgViewH - actH)/2;
int left = (int) (imgViewW - actW)/2;
if(origW!=actW){
m_mainActivity.setTextMeasured(true);
m_mainActivity.setTextLayout(origW, origH, actW, actH,top,left);
}
}
}
Пожалуйста, делитесь девять патч изображения – LaurentY
Здесь вы идете. Загружено. – ahtartam
Я считаю, что этот ответ объясняет проблему довольно хорошо: [Android-контент с девятью патчами не соблюден] (http://stackoverflow.com/a/20962766/383414). Подумайте с точки зрения «заполнения» вокруг области содержимого, вместо того, чтобы думать о реальном содержании. –