TransitionDrawable doesn't account for padding? - android

I tried the accepted solution posted here, but it appears to ignore padding. When the second view (in this case a button) displays, it's much smaller than the original which has padding. Is there a workaround for that? Thanks

Yes, TransitionDrawable extends from LayerDrawable which ignores the padding. This is the getPadding() method in the base Android code, which gets rid of anything you specified:
#Override
public boolean getPadding(Rect padding) {
// Arbitrarily get the padding from the first image.
// Technically we should maybe do something more intelligent,
// like take the max padding of all the images.
padding.left = 0;
padding.top = 0;
padding.right = 0;
padding.bottom = 0;
final ChildDrawable[] array = mLayerState.mChildren;
final int N = mLayerState.mNum;
for (int i=0; i<N; i++) {
reapplyPadding(i, array[i]);
padding.left += mPaddingL[i];
padding.top += mPaddingT[i];
padding.right += mPaddingR[i];
padding.bottom += mPaddingB[i];
}
return true;
}
See base Android code here.
To deal with it, I had to first save the padding values before setting the faulty drawable background on my view:
int bottom = theView.getPaddingBottom();
int top = theView.getPaddingTop();
int right = theView.getPaddingRight();
int left = theView.getPaddingLeft();
theView.setBackgroundResource(R.drawable.faulty_drawable);
theView.setPadding(left, top, right, bottom);

Related

Remove Background of an Image, Split it in same sizes and Change color(overlay)

I've been searching the internet for changing colour or overlaying a specific part of a bitmap. I've a square bitmap and I want to change the colour in a matrix pattern that is in equal 9 blocks which can be understood from the following image. (Cyan colour line here is for demonstration only)
I've read about boundary fill algorithm in College but here for java, I came to know that it is too bulky to perform such an operation for 9 specific parts. And I don't know how to use Paint with Canvas for such a square scenario.
So is there a method or something which can help me figure out how to paint a specific square by providing the size or location without performing a huge task on UI.
Here's what I need to achieve:
I can change the color, location,size by myself if there's something which can help me out.
Also, as there is white background, is there a way to not paint the background or do I have to use PNG?
Update:
I'm successfully able to divide the image in 9 equal parts using following code but PorterDuffColorFilter is not working as expected.
Code:
public void splitBitmap(Bitmap bitmap) {
int width, height;
// Divide the original bitmap width by the desired vertical column count
width = bitmap.getWidth() / 3;
// Divide the original bitmap height by the desired horizontal row count
height = bitmap.getHeight() / 3;
// Loop the array and create bitmaps for each coordinate
for (int x = 0; x < 3; ++x) {
for (int y = 0; y < 3; ++y) {
// Create the sliced bitmap
smallimages.add(Bitmap.createBitmap(bitmap, x * width, y * height, width, height));
}
}
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
}
The above code provides 9 bitmaps which then set to a GridLayout. But No mode of PorterDuffColorFilter is useful. Either the images remain original or is painted completely. I've tried every one of the modes available and none worked.
I've done something similar to this so after changing my code a bit, I think this is what you want:
Assuming that you don't have PNG,
First, remove the white background from your image Source:
Setting the white color as Transparent, you can use any color you want.
private static final int[] FROM_COLOR = new int[]{255, 255, 255};
private static final int THRESHOLD = 3;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.test_colors);
ImageView iv = (ImageView) findViewById(R.id.img);
Drawable d = getResources().getDrawable(RES);
iv.setImageDrawable(adjust(d));
}
private Drawable adjust(Drawable d)
{
int to = Color.TRANSPARENT;
//Need to copy to ensure that the bitmap is mutable.
Bitmap src = ((BitmapDrawable) d).getBitmap();
Bitmap bitmap = src.copy(Bitmap.Config.ARGB_8888, true);
for(int x = 0;x < bitmap.getWidth();x++)
for(int y = 0;y < bitmap.getHeight();y++)
if(match(bitmap.getPixel(x, y)))
bitmap.setPixel(x, y, to);
return new BitmapDrawable(bitmap);
}
private boolean match(int pixel)
{
//There may be a better way to match, but I wanted to do a comparison ignoring
//transparency, so I couldn't just do a direct integer compare.
return Math.abs(Color.red(pixel) - FROM_COLOR[0]) < THRESHOLD &&
Math.abs(Color.green(pixel) - FROM_COLOR[1]) < THRESHOLD &&
Math.abs(Color.blue(pixel) - FROM_COLOR[2]) < THRESHOLD;
}
Above code will change the color to transparent and below code will split the bitmap into 9 same size bitmaps:
public void splitBitmap(Bitmap bitmap) {
ArrayList<Bitmap> smallimages = new ArrayList<>(9);
int width, height;
// Divide the original bitmap width by the desired vertical column count
width = bitmap.getWidth() / 3;
// Divide the original bitmap height by the desired horizontal row count
height = bitmap.getHeight() / 3;
// Loop the array and create bitmaps for each coordinate
for (int x = 0; x < 3; ++x) {
for (int y = 0; y < 3; ++y) {
// Create the sliced bitmap
smallimages.add(Bitmap.createBitmap(bitmap, x * width, y * height, width, height));
}
}
}
At last, you can use PorterDuffColorFilter on every bitmap:
imageView.setImageDrawable(arrayList.get(0));
imageView.setColorFilter(Color.BLACK, PorterDuff.Mode.SRC_ATOP);
There can be problems as it works for me and might not for you but this is the way you can achieve your needed result.
If any problem persists, I can help.

Interchange positions of two Views within GridLayout (Android)

I have programmed a basic gaming App that consists of blocks which can be exchanged by a swipe (similar to CandyCrush). I succeeded in recognizing the swipe gesture but my code that changes the positions of the Views (blocks) within a GridLayout does only work in the emulator but not on a real device (Samsung Galaxy S3).
Also I couldn't find a way of animating the interchange of the two views. I've added android:animateLayoutChanges="true" to the GridLayout XML but it didn't change anything.
Here's my exchanging code:
// change to blocks positions in grid layout
GridLayout.LayoutParams sourceParams = (GridLayout.LayoutParams)this.imageView.getLayoutParams();
GridLayout.LayoutParams targetParams = (GridLayout.LayoutParams)otherBlock.imageView.getLayoutParams();
GridLayout.Spec sourceRowSpec = sourceParams.rowSpec;
GridLayout.Spec sourceColumnSpec = sourceParams.columnSpec;
sourceParams.rowSpec = targetParams.rowSpec;
sourceParams.columnSpec = targetParams.columnSpec;
targetParams.rowSpec = sourceRowSpec;
targetParams.columnSpec = sourceColumnSpec;
this.imageView.setLayoutParams(sourceParams);
otherBlock.imageView.setLayoutParams(targetParams);
gameGridLayout.requestLayout();
And here's a screenshot of the App:
You should have an index table of your layout, and in your drawing method you run through this index to draw each block.
Like that:
private int [][] index;
void onDraw(Canvas canvas) {
for (int i = 0; i < MAX_BLOCK_HEIGHT; i++) {
for (int j = 0; j < MAX_BLOCK_WIDTH; j++) {
// Draw block index[i][j]
}
}
}
void swapBlock(int blockX, int blockY, int relativePos) {
int tmpBlock = index[blockY][blockX];
if (relativePos == AT_LEFT) {
index[blockY][blockX] = index[blockY][blockX - 1];
index[blockY][blockX - 1] = tmpBlock;
}
// And so on...
}
And this index can be helpful all the time, not only for blit.

How to detect color line in image using android java

If I have an image containing black lines, like the image below. How can I detect the black lines.( to know the x,y of dots on this lines) ?
I want to know how to get started with this topic. What library should I learn to go through
You can use Catalano Framework.
http://code.google.com/p/catalano-framework/
FastBitmap image = new FastBitmap(bitmap);
image.toGrayscale();
int width = image.getWidth();
int height = image.getHeight();
ArrayList<IntPoint> lst = new ArrayList<>();
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
if (image.getGray(i, j) == 0)
lst.add(new IntPoint(i,j));
}
}

Color correction on android

i am new in android programming. Now i am doing a color correction program using java for android platform.
In the program, i should be able to select a point on the bitmap and tell the program that it is actually white color, and the program will re-adjust all the pixels of that bitmap so that all the colors of that bitmap will be correct.
Can anyone tell me how can i do this? I am already able to retrieve a point from a bitmap now and calculate its RGB, but i got no idea how i can carry on. Please show me some examples or articles that i can read up on.
Thank you so much for your precious time. Hope to hear from you soon!
Resulting photo :
http://www.flickr.com/photos/92325795#N02/8392038944/in/photostream
My photo is being updated and despite of the quality/noise/color, there are the weird colors here and there. Anyone have any idea what i should do to remove it? Or even better improve on the method i am using? Heres the code:
The input is the bitmap to edit, inColor is the color of the nose in the photo to be edited, reqcolor is the color of my nose in the sample/optimum photo.
public Bitmap shiftRGB(Bitmap input, int inColor, int reqColor){
int deltaR = Color.red(reqColor) - Color.red(inColor);
int deltaG = Color.green(reqColor) - Color.green(inColor);
int deltaB = Color.blue(reqColor) - Color.blue(inColor);
//--how many pixels ? --
int w = input.getWidth();
int h = input.getHeight();
//-- change em all! --
for (int i = 0 ; i < w; i++){
for (int j = 0 ; j < h ; j++ ){
int pixColor = input.getPixel(i,j);
//-- colors now ? --
int inR = Color.red(pixColor);
int inG = Color.green(pixColor);
int inB = Color.blue(pixColor);
if(inR > 255){ inR = 255;}
if(inG > 255){ inG = 255;}
if(inB > 255){ inB = 255;}
if(inR < 0){ inR = 0;}
if(inG < 0){ inG = 0;}
if(inB < 0){ inB = 0;}
//-- colors then --
input.setPixel(i,j,Color.argb(255,inR + deltaR,inG + deltaG,inB + deltaB));
}
}
return input;
}
Thank you so much for help me! I cant express my gratitude further than saying another thank you in advance!
Read about some white-balancing algorithms. See if you can implement some. Also note that android does not provides awt.graphics / BufferedImage API, used in majority of java tutorials out there.
Android provides ColorMatrixColorFilter, for such use, discussed here.
A basic crude way to manipulate pixels:
public Bitmap shiftRGB(Bitmap input, int inColor, int reqColor){
//--how much change ? --
int deltaR = Color.red(reqColor) - Color.red(inColor);
int deltaG = Color.green(reqColor) - Color.green(inColor);
int deltaB = Color.blue(reqColor) - Color.blue(inColor);
//--how many pixels ? --
int w = input.getWidth();
int h = input.getHeight();
//-- change em all! --
for (int i = 0 ; i < w; i++){
for (int j = 0 ; j < h ; j++ ){
int pixColor = input.getPixel(i,j);
//-- colors now ? --
int inR = Color.red(pixColor);
int inG = Color.green(pixColor);
int inB = Color.blue(pixColor);
//-- colors then --
input.setPixel(i,j,Color.argb(255,inR + deltaR,inG + deltaG,inB + deltaB));
}
}
//-- all done--
return input;
}

How to find android TextView number of characters per line?

So I have a TextView in android that has the width of the whole length of the screen and a padding of dip 5. How can I calculate the number of characters that will fit a single line on the screen? I guess in other words, I'm trying to get the number of columns of a textview?
I considered manual calculation depending on textsize and width, but 1) don't know the correlation and 2) due to the padding in the units of dip, different screens will use different number of actual pixels to pad.
Overall Question: I am trying to use this to solve: if given a string how can I manually edit to string such that when the textview prints the string character by character, I will know when to start a word that won't fit on one line on the next. Note: I know that textview automatically puts words that won't fit onto the next line, however, since I'm printing character by character, like typing animation, textview doesn't know the word won't fit until it prints out the overflowing characters of that word.
Been searching everywhere for this...
Thanks!
Added solutions:
one possible solution:
public String measure2 (TextView t, String s) {
String u = "";
int start = 0;
int end = 1;
int space = 0;
boolean ellipsized = false;
float fwidth = t.getMeasuredWidth();
for(;;) {
//t.setText(s.substring(start, end));
float twidth = t.getPaint().measureText(s.substring(start, end));
if (twidth < fwidth){
if (end < s.length())
end++;
else {
if (!ellipsized)
return s;
return u + s.subSequence(start, end);
}
}
else {
ellipsized = true;
space = (u + s.substring(start, end)).lastIndexOf(" ");
if (space == -1)
space = end - 1;
u += s.subSequence(start, space) + "\n";
start = space + 1;
end = start + 1;
}
}
}
solution 2, but still uses solution1 sometimes:
public String measure3 (TextView t, String s) {
List<String> wlist = Arrays.asList(s.split(" "));
if (wlist.size() == 1)
return measure2(t, s);
String u = "";
int end = 1;
float fwidth = t.getMeasuredWidth();
for(;;) {
//t.setText(s.substring(start, end));
if (wlist.isEmpty())
return u;
String temp = listStr(wlist, end);
float twidth = t.getPaint().measureText(temp);
if (twidth < fwidth){
if (end < wlist.size())
end++;
else {
return u + temp;
}
}
else {
temp = listStr(wlist, end-1);
if (end == 1)
temp = measure2(t, temp);
if (wlist.isEmpty())
return u + temp;
else
u = u + temp + "\n";
wlist = wlist.subList(end - 1, wlist.size());
end = 1;
}
}
}
public String listStr (List<String> arr, int end) {
String s = "";
for (String e : arr.subList(0, end) ){
s = s + e + " ";
}
return s.trim();
}
I used the above code to generate off a original string s, a string u that would be printed. However, I think this approach is very inefficient. Is there another approach or a better algorithm? Note: there are some errors in measure3 that I fixed, but was too lazy to edit
Try this:
private boolean isTooLarge (TextView text, String newText) {
float textWidth = text.getPaint().measureText(newText);
return (textWidth >= text.getMeasuredWidth ());
}
Detecting how many characters fit will be impossible due to the variable width of the characters. The above function will test if a particular string will fit or not in the TextView. The content of newText should be all the characters in a particular line. If true, then start a new line (and using a new string to pass as parameter).
Answer to the comment:
because the app can be run in many systems is exactly why you need to measure it.
This is a way to solve your "overall question". What is the difference between using str.size()>numCol vs is too large? You will need to implement your animation (hint #1: insert a newline character)
as I said before when you start a new line, you start a new string (hint #2: if you extend TextView, you can implement all this in overriding setText). (hint #3: Keep track of the lines created with a static int lines; and use newString.split("\\r?\\n")[lines-1] to check for length).
You can get total line of Textview and get string for each characters by below code.Then you can set style to each line whichever you want.
I set first line bold.
private void setLayoutListner( final TextView textView ) {
textView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
textView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
final Layout layout = textView.getLayout();
// Loop over all the lines and do whatever you need with
// the width of the line
for (int i = 0; i < layout.getLineCount(); i++) {
int end = layout.getLineEnd(0);
SpannableString content = new SpannableString( textView.getText().toString() );
content.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, end, 0);
content.setSpan(new StyleSpan(android.graphics.Typeface.NORMAL), end, content.length(), 0);
textView.setText( content );
}
}
});
}
Try this way.You can apply multiple style this way.
I had the same issue and I calculated the number characters per line by 2 steps:
Step 1: Calculate the number of lines
val widthOfTvComment = widthOfScreen - marginLeft - marginRight
var bounds = Rect()
var paint = Paint()
paint.textSize = textSize
paint.getTextBounds(comment,0,comment.length,bounds)
val lines = ( bounds.width()/widthOfTvComment)
Step 2: Calculated the number characters per line
val charactersPerLine = comment.length / lines

Categories

Resources