3

I'm trying to make a frame for TextView as a cloud. But the content area does not behave as expected. What am i doing wrong?enter image description here

nine-patch not working

enter image description here

ahtartam
  • 879
  • 9
  • 13

4 Answers4

1

I have a suggestion that is not working properly because the content area less scale area. So sad. I remade it to handle 9-patch manually. Save pictures without .9.png. Get Bitmap. There are 9-line present. With getPixels calculated padding and set it on the TextView. After that calculating and set LayoutParams.width and LayoutParams.height. Looks a bit ugly, but it works quite quickly, and most importantly correctly.

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);
}
});
ahtartam
  • 879
  • 9
  • 13
0

You set good values for right and bottom borders. You just have to set same values for left and top borders, left border = right border and top border = bottom border.

The result in draw9patch: enter image description here

And here the 9-patch file:

enter image description here

For your information, your image is not really suitable for using with 9-patch format.

LaurentY
  • 7,495
  • 3
  • 37
  • 55
0

I extended/adapted @ahtartam code. I am not sure if it is the cleanest way but it works for me. If someone needs help, just contact me or ask in comments!

    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();

}

Instead TextView I use SizeAwareImageView from -> https://stackoverflow.com/a/15538856/1438596

In my case it looks like 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);
            }

        }
    }
Community
  • 1
  • 1
namik
  • 53
  • 1
  • 8
-1

You could use this tool for creating your nine-patch images.

Catalina
  • 1,954
  • 1
  • 17
  • 25