I am trying to create dynamic buttons at the center of spesific areas of the ImageView. To figure out center of any area, I am using this function:
TextView createButton(int i, String[] boundingBoxArray) {
String[] coorArray = boundingBoxArray[i].split(",");
int[] coordinates = new int[4];
int x11 = Integer.parseInt(coorArray[0].replace(" ", ""));
int y11 = Integer.parseInt(coorArray[1].replace(" ", ""));
int x22 = Integer.parseInt(coorArray[2].replace(" ", ""));
int y22 = Integer.parseInt(coorArray[3].replace(" ", ""));
coordinates[0] = x11;
coordinates[1] = y11;
coordinates[2] = x22;
coordinates[3] = y22;
TextView buttonn = new TextView(context);
buttonn.setText(String.valueOf(i + 1));
buttonn.setTextSize(15);
buttonn.setId(i + 1);
buttonn.setBackgroundResource(R.drawable.circle);
RelativeLayout.LayoutParams rel_btn
= new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
Rect bounds = imageView.getDrawable().getBounds();
int scaledHeight = bounds.height();
int scaledWidth = bounds.width();
double scale;
double differWidth = 0;
double differHeight = 0;
imageViewHeight = imageView.getHeight();
imageViewWidth = imageView.getWidth();
if (scaledHeight > scaledWidth) {
scale = ((double) imageViewHeight / (double) scaledHeight);
differWidth = (imageViewWidth - (scaledWidth * scale)) / 2;
} else {
scale = ((double) imageViewWidth / (double) scaledWidth);
differHeight = (imageViewHeight - (scaledHeight * scale)) / 2;
}
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int swidth = displaymetrics.widthPixels;
int buttonWidth = swidth / 30;
double a = ((double) (x11 + x22) / 2) * scale - buttonWidth + differWidth;
double b = ((double) (y11 + y22) / 2) * scale - buttonWidth + differHeight;
rel_btn.leftMargin = (int) a;
rel_btn.topMargin = (int) b;
rel_btn.width = 2 * buttonWidth;
rel_btn.height = 2 * buttonWidth;
buttonn.setGravity(Gravity.CENTER);
buttonn.setLayoutParams(rel_btn);
return buttonn;
}
When the activity starts, this function is called in for loop (number of loop is depends on number of areas) to create buttons on the ImageView. When all buttons are created, user can click on one of any dynamic button to focus on the spesific area.
If the user click on any button, the createButton() function is called again (it doesnt necessary but it doesnt make an issue either) for some purposes.
The problem is height of ImageView is not fixed. At the first time of calling createButton() function, the height returns as greater than the normal height. Then if you call createButton() again, the height returns the normal value.
imageViewHeight = imageView.getHeight();
imageViewWidth = imageView.getWidth();
The class has 2-3 nested thread, so maybe this is cause of problem. But I tried lots of things like:
I used CountDownLatch to handle threads and functions
I used mImageView.post(new Runnable...) to be sure to call functions after imageView is created.
I called imageView.getHeight() lots of
different places, but nothing is changed.
I keep the expression long, because I couldn't decided if the information is enough to understand. And as you realize, English is not my native. Thank you.
Edit: I forgot to mention: Below API 19, everything is cool (getHeight() value is returning as the normal size, either at the first time of calling createButton() methor or later ). API 20 and above, I get this error.
I luckily found the solution.. I use fullscreen mode at my app, but I didn't use AreaSelectActivity in fullscreen. After activity opened, status bar is coming down in a while. That's why height is changed but length is not. I put AreaSelectActivity in fullscreen mode and bum ! it is fixed now.
Related
This is a little bit complicated to explain, so apologies.
The basic requirement is annotator app on Android, which allows the user to draw over the desktop, take a snapshot and one or two other things.
When the app starts it shows a single icon. This can be moved about the desktop.
When this icon is single clicked (touch) 6 icons spread evenly centred around the central icon appear.
So far so good. Now we move the central icon, and re-calculate the positions of the 6 outer icons centred around the new position of the central icon.
What we find is the outer icons are off centre relative to the central icon. The displacement looks to be roughly equal (bot X and Y) by the position of the touch within the central icon.
I will attempt to draw what happens.
First when the touch point on the drag/move is in the centre, everything lines up perfectly:
When the touch point is to the right, the displacement is leftwards as below:
When the touch is at the bottom the displacement is upwards:
The position of the "x" relative to the icon is it seems from
int shiftX = event.getX();
int shiftY = event.getY();
The position of the moved icon is from :
view.getLocationInWindow(locWXY);
int X = locWXY[0];
int Y = locWXY[1];
So, the positions of the satellite icons are calculated as:
final double angle = 30.000;
final double rad = angle * Math.PI / 180.000;
final int radius = 100;
final int penX = (int) (X + radius * cos(rad) + shiftX);
final int penY = (int) (Y - radius * sin(rad) + shiftY);
final int clearX = X ;
final int clearY = (int) (Y - radius + shiftY);
final int closeX = (int) (X - radius * cos(rad) + shiftX);
final int closeY = (int) (Y - radius * sin(rad) + shiftY);
final int iFlipX = (int) (X - radius * cos(rad) + shiftX);
final int iFlipY = (int) (Y + radius * sin(rad) + shiftY);
final int sshotX = X + shiftX;
final int sshotY = (int) (Y + radius + shiftY);
final int iFolderX = (int) (X + radius * cos(rad) + shiftX);
final int iFolderY = (int) (Y + radius * sin(rad) + shiftY);
penLP= new RelativeLayout.LayoutParams(70, 70);
penLP.leftMargin = penX;
penLP.topMargin = penY;
imbBlackPen.setLayoutParams(penLP);
clearLP = new RelativeLayout.LayoutParams(70, 70);
clearLP .leftMargin = clearX;
clearLP .topMargin = clearY;
imbClearScreen.setLayoutParams(clearLP );
folderLP = new RelativeLayout.LayoutParams(70, 70);
folderLP .leftMargin = iFolderX ;
folderLP .topMargin = iFolderY;
imbFolder.setLayoutParams(folderLP );
sshotLP = new RelativeLayout.LayoutParams(70, 70);
sshotLP .leftMargin = sshotX ;
sshotLP .topMargin = sshotY;
imbScreenCapture.setLayoutParams(sshotLP );
iFlipLP = new RelativeLayout.LayoutParams(70, 70);
iFlipLP .leftMargin = iFlipX ;
iFlipLP .topMargin = iFlipY;
imbIflipChart.setLayoutParams(iFlipLP );
closeLP = new RelativeLayout.LayoutParams(70, 70);
closeLP .leftMargin = closeX ;
closeLP .topMargin = closeY;
imbClose.setLayoutParams(closeLP );
I have tried setting shiftX and shiftY to zero, calculating X and X + shiftX/2. All to no avail. The strange thing is that on a small 10 inch tablet with resolution 1920 x 1200 it looks almost perfect, but on a large 65 inch touch screen the displacement is extremely pronounced.
We must be missing something, but I cannot figure out what.
As commented above ...
Fixed. The icon position calculation code above needed to be executed on ACTION_UP as well as ACTION_DOWN. Refactored this as a method and called it on both these events.
How can I get current position of thumb in pixel for SeekBar?
Currently I am trying to get the position on the bases of calculation.
Screen width, Seek Bar width, current seek progress and all. But I am not able to get exact position out of it.
Do any one have any idea?
Coding for same is as below.
I want to drow one component on top of SeekBar thumb.
translation = calculateTranslation(this.deviceScreenWidth, seekBarWidth, seekBar1T.getMax(), Integer.valueOf(ConstantData.seekbar_fifth.toString()), topComponentWidth, 0);
if (currentapiVersion < android.os.Build.VERSION_CODES.HONEYCOMB){
TranslateAnimation anim = new TranslateAnimation(translation - 1,
translation, 0, 0);
anim.setFillAfter(true);
anim.setDuration(0);
edtTextRodUpDown.startAnimation(anim);
}else{
edtTextRodUpDown.setTranslationX(translation);
}
and calculate Translation like
private float calculateTranslation(int screenWidth, int seekBarWidth, int seekMaxProgress, int currentProgress, int componentWidth, int extraDifference){
double calculatedPosition = 0f;
calculatedPosition = (double)((double)(seekBarWidth-((screenWidth-seekBarWidth))) / (double)seekMaxProgress) * (double)currentProgress;
calculatedPosition = calculatedPosition - (double)(componentWidth/2);
calculatedPosition = calculatedPosition + extraDifference;
Double d = new Double(calculatedPosition);
if(d < 0){
return 0.0f;
}else if(d + componentWidth > screenWidth){
return screenWidth-componentWidth;
}else{
return d.floatValue();
}
}
I did this:
int width = seekBar.getWidth()
- seekBar.getPaddingLeft()
- seekBar.getPaddingRight();
int thumbPos = seekBar.getPaddingLeft()
+ width
* seekBar.getProgress()
/ seekBar.getMax();
You can use the getBounds() to get this info.
This sample code below is for instance aligning a TextView with the seekbar thumb position.
TextView sliderIndicator = ...
Rect bounds = seekBar.getThumb().getBounds();
sliderIndicator.setTranslationX(seekBar.getLeft() + bounds.left);
The seekbar thumb has a thumb offset, which is basically a slight shift to the right. So you have to make sure that you take this into account as well:
int thumbPos = seekbar.getMeasuredWidth() * seekbar.getProgress() / seekbar.getMax() - seekbar.getThumbOffset();
Hii everyone currently iam working on scanning qr code from my app and i have used zxing library and it's working good and my problem is in my galaxy s4 mobile the scanning area is very small
Please help me
thanks in advance
I know it is too much late but help for others
just go to camera manager class and paste this code on replacement of given method
it works for all types of screens
public Rect getFramingRect() {
if (framingRect == null) {
if (camera == null) {
return null;
}
Point screenResolution = configManager.getScreenResolution();
int width = screenResolution.x * 3 / 4;
int height = screenResolution.y * 3 / 4;
Log.v("Framing rect is : ", "width is "+width+" and height is "+height);
int leftOffset = (screenResolution.x - width) / 2;
int topOffset = (screenResolution.y - height) / 2;
framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
Log.d(TAG, "Calculated framing rect: " + framingRect);
}
return framingRect;
}
public Rect getFramingRect() {
if (framingRect == null) {
if (camera == null) {
return null;
}
Point screenResolution = configManager.getScreenResolution();
int screenx = screenResolution.x;
int screeny = screenResolution.y;
int width, height, left, top;
if (screenx > screeny) {
width = (int) (screenx * 12.5 / 100);
height = (int) (screeny * 25 / 100);
left = (int) screenx * 83 / 100;
top = (int) screeny * 75 / 100;
} else {
left = (int) (screenx * 12.5 / 100);
top = (int) (screeny * 25 / 100);
width = (int) screenx * 83 / 100;
height = (int) screeny * 75 / 100;
}
framingRect = new Rect(left,top, width, height);
Log.d(TAG, "Calculated framing rect: " + framingRect);
}
return framingRect;
}
Replace the above code in CameraManager.java file
this worked for me try this out
The CameraManager class has two constants defined MIN_FRAME_WIDTH and MIN_FRAME_HEIGHT. You should modify them as desired and everything should work:
private static final int MIN_FRAME_WIDTH = 240; // (your desired value here)
private static final int MIN_FRAME_HEIGHT = 240; // (your desired value here)
If you are calling this from another android app, use intent extras SCAN_WIDTH and SCAN_HEIGHT for this.
If you happen to be using phonegap-plugin-barcodescanner (3.0.0 or later), then passing the same intents like xxxxx.scan(onSuccessFunc,onFailFunc,{SCAN_HEIGHT:111,SCAN_WIDTH:222}) will produce the same result. 111 being the height, and 222 being the width.
If you are using ZxingScannerView, you can override createViewFinderView() and increase or decrease the framing rectangle size via viewFinderView like this :
scannerView = object : ZXingScannerView(requireContext()) {
override fun createViewFinderView(context: Context?): IViewFinder {
val viewfinderView = super.createViewFinderView(context)
viewfinderView.setViewFinderOffset(-90) // increase size of framing rectangle
return viewfinderView;
}
}
yourLayour.addView(scannerView)
scannerView.startCamera()
I have the following code called in my Android application. When I run it on an old Samsung Dart (api < 13), I get a NullPointer exception as noted below.
Is there a particular reason the code is working for the four lines above it but not the line it is getting the NullPointer?
#SuppressLint("NewApi")
#SuppressWarnings("deprecation")
public void adjustSize() {
int width, height;
Display display = getWindowManager().getDefaultDisplay();
if (android.os.Build.VERSION.SDK_INT >= 13) {
Point size = new Point();
display.getSize(size);
width = size.x;
height = size.y;
} else {
width = display.getWidth(); // deprecated
height = display.getHeight(); // deprecated
}
ImageView counties = (ImageView) findViewById(R.id.btnCounties);
ImageView members = (ImageView) findViewById(R.id.btnMembers);
ImageView webLink = (ImageView) findViewById(R.id.btnWebLink);
ImageView logo = (ImageView) findViewById(R.id.logo);
// Calculate image sizes
if (height > width) {
counties.getLayoutParams().height = (int) (width / 2.5);
counties.getLayoutParams().width = (int) (width / 2.5);
members.getLayoutParams().height = (int) (width / 2.5);
members.getLayoutParams().width = (int) (width / 2.5);
webLink.getLayoutParams().height = (int) ((width / 2.4) / 3.5); // Null pointer error
webLink.getLayoutParams().width = (int) (width / 2.4);
logo.getLayoutParams().height = (int) (height / 6);
logo.getLayoutParams().width = width;
} else {
counties.getLayoutParams().height = (int) (height / 2.5);
counties.getLayoutParams().width = (int) (height / 2.5);
members.getLayoutParams().height = (int) (height / 2.5);
members.getLayoutParams().width = (int) (height / 2.5);
}
}
Simply,
ImageView webLink = (ImageView) findViewById(R.id.btnWebLink);
webLink is null.
Check your layout xml: are you sure the name (btnWebLink) is correct? Are you sure you're loading the correct layout xml file?
Probabily you have the ImageView in one layout but Android is loading the layout for a specific screen size where there's no btnWebLink.
Have a breakpoint in that line and check if the variable webLink is null.
The null pointer exception comes the first time you try to use the variable.
i have an image that rotates around an arbitrary point. but i need 3 such images to rotate simultaneously
this is how i try to implement the same
private void rotateLogo(float degrees){
Matrix matrix1 = new Matrix();
//int radius = turntable.getWidth()/2;
double radians = degrees* (Math.PI/180);
double xcoordinate = 220 * Math.cos(radians)- 60;
double ycoordinate = 220 * Math.sin(radians) + 50;
matrix1.postRotate((int)radians, 220, 220);
// people image
FrameLayout.LayoutParams linLay = (FrameLayout.LayoutParams) peopleLogo.getLayoutParams();
linLay.bottomMargin = (int)ycoordinate + 10;
linLay.rightMargin = (int)xcoordinate + 10;
peopleLogo.setImageMatrix(matrix1);
peopleLogo.setLayoutParams(linLay);
rotateLogo2(degrees - 2);
}
private void rotateLogo2(float degrees){
double radians = degrees* (Math.PI/180);
double xcoordinate = 220 * Math.cos(radians)- 60;
double ycoordinate = 220 * Math.sin(radians) + 50;
// people image
FrameLayout.LayoutParams linLay = (FrameLayout.LayoutParams) serverLogo.getLayoutParams();
linLay.bottomMargin = (int)ycoordinate + 10;
linLay.rightMargin = (int)xcoordinate + 10;
serverLogo.setLayoutParams(linLay);
}
in the above code i reduced the angle and rotate the second image using the same code, but the image doesnt rotate, it just disappears on touch.
i also tried to take the layout params of the first image before rotation and apply the same to the second image, but this doesnt work too..
the image disappears on rotation though at times it appears and then disappears
can anyone help me as to where i could be wrong or suggest any other approaches for the same?
You can refactor the code
private void rotateLogo(View logo, float degrees){
Matrix matrix1 = new Matrix();
//int radius = turntable.getWidth()/2;
double radians = degrees* (Math.PI/180);
double xcoordinate = 220 * Math.cos(radians)- 60;
double ycoordinate = 220 * Math.sin(radians) + 50;
matrix1.postRotate((int)radians, 220, 220);
// people image
FrameLayout.LayoutParams linLay = (FrameLayout.LayoutParams) logo.getLayoutParams();
linLay.bottomMargin = (int)ycoordinate + 10;
linLay.rightMargin = (int)xcoordinate + 10;
if (logo isInstanceOf ImageView) {
logo.setImageMatrix(matrix1);
}
logo.setLayoutParams(linLay);
}
and call the method twice with different parameters..
rotateLogo(peopleLogo, degrees);
rotateLogo(serverLogo, degrees-2);