I am developing an android app in which I need to display the saved gesture to the user. I have tried doing it using the GestureOverlayView object's setGesture() function but it displays the gesture well outside the screen. Only small portion is visible in the left top corner of the screen in the Android emulator 2.1.
Here is the code that I have used..
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.savegesture);
gestureoverlay = (GestureOverlayView) findViewById(R.id.gestures_overlay2);
mOldGesture = (Gesture) getIntent().getExtras().get("gesture");
mDoneButton = findViewById(R.id.done);
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
gestureoverlay.setLayoutParams(new FrameLayout.LayoutParams(dm.widthPixels,dm.heightPixels,0x50));
gestureoverlay.setGesture(mOldGesture);
gestureoverlay.invalidate();
}
The android GestureOverlayView defined in "savegesture.xml" is as follows:-
<android.gesture.GestureOverlayView android:scaleType="center" android:layout_gravity="center"
android:id="#+id/gestures_overlay2" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:gestureStrokeType="multiple" />
I don't know what the problem is, but it won't show the gesture ON the screen....
Although this is a 3 year old question, I'll still add an answer.
The gesture appears outside the GestureOverlayView because it's been set in onCreate. It must be set after the layout measurements have been computed.
ViewTreeObserver can be used to know when the layout has been measured.
ViewTreeObserver vto = gestureoverlay.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
gestureoverlay.getViewTreeObserver().removeGlobalOnLayoutListener(this);
gestureoverlay.setGesture(mOldGesture);
}
});
Altough this is a 5 year old question, I'll still add an answer, because the approved answer is inefficient in comparison to this:
Use view.post() to execute code after the view has been loaded.
gestureoverlay.post(new Runnable() {
#Override
public void run() {
gestureoverlay.setGesture(mOldGesture);
}
});
Related
I have a layout with some Views that I need to change size depending on some parameters, that depend on width of the View. The width is set to "match_parent". So when I try to get the width it returns 0. Here is what I have tried so far:
mask.getWidth();
mask.getLayoutParams().width
ViewTreeObserver vto = mask.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
mask.getViewTreeObserver().removeGlobalOnLayoutListener(this);
int width = mask.getMeasuredWidth();
}
});
So my question is how do I get the width in this situation?
Thank you.
After digging around I found a solution that answers my question but has a major problem that I am yet to resolve. We can use method post() that every View has and adds a Runnable to the message queue. So as I understand what happens is after View is fully measured in method post() we can get dimensions that we need like this:
holder.button.post(new Runnable() {
#Override
public void run() {
width = holder.button.getWidth();
}
});
However the problem here is that RecyclerView won't wait until this view is measured as and will go to next row and rows won't be updated according to measures that you expect.
If anyway has a way to go about this problem please leave a comment. Thank you.
I'm working on an Android TV app and need to make a progress bar to indicate how much content has been played already. I feel like what I've written should be working, but it isn't.
I've got a LinearLayout with android:orientation="horizontal" and android:weightSum=100 as a container for the progress bar, and the actual progress bar is a FrameLayout inside the container, with android:layout_width="0dp" and android:layout_weight="0" to make sure the progress bar isn't drawn if there isn't any progress.
In the activity code I'm attempting to change the weight of the progress bar like this:
ViewGroup.LayoutParams lp = progressView.getLayoutParams();
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(lp.width, lp.height, progress);
progressView.setLayoutParams(params);
(progressView, naturally, is the progress bar object I'm trying to manipulate, and progress is the intended new weight)
I was initially running this code in the activity's onCreate() method, until I remembered you can't do anything about a view's dimensions until it has been laid out properly. Since then I've tried running this in onResume() with postDelayed like this:
#Override
public void onResume() {
super.onResume();
progressView.postDelayed(new Runnable() {
#Override
public void run() {
setProgress();
}
}, 1000);
}
and with a ViewTreeObserver like this during onCreate():
progressView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (!progressBarRefreshed) {
setProgress();
}
}
});
and I've even tried running the code as an onClick event attached to a button in the same activity (in both cases setProgress() is the function that performs the weight change using the code posted above). I've verified (with log messages I removed from the code to make it more readable) that the initial width is 0, height is -1 (match_parent) and weight is 0, and that the new LayoutParams object has width 0, height -1 and weight equal to whatever I set it to. But after the setLayoutParams() call the view still has weight 0 and there is no change on the screen either. What blatantly trivial thing am I missing here?
Try calling progressView.requestLayout() after setting the layout params.
I'm getting height and width of a view, inflated in the getView() method. It's a grid item.
Usually I use post() on the view to get the size, after it was attached to the layout. But it returns 0.
final View convertViewFinal = convertView;
convertView.post(new Runnable() {
#Override
public void run() {
doSomethingWithConvertView(convertViewFinal);
}
});
...
doSomethingWithConvertView(View v) {v.getWidth(); /*returns 0*/};
How do I get the size?
While using a viewTreeObserver definitely works, I have found that calling measurements requirements on inflated views can be done reliably using a runnable from the activity's view. i.e.
someActivityInstance.getWindow().getDecorView().post(new Runnable() {
#override
public void run() {
// someMeasurements
}
});
The thing is that convertview most likely is not drawn on the phone screen yet, so you have to wait until it is ready.
You need to use a ViewTreeObserver, to know exactly when the view has been drawn.
Check this answer for more info:
When Can I First Measure a View?
You probably is calling this at onCreate or onStart or onResume, methods which runs before layout measure.
But there is a lot of work arounds, this is one good option:
ViewTreeObserver vto = rootView.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
public void onGlobalLayout() {
v.getWidth();//already measured...
}
});
Where rootView may be any viewGroup in a higher level than the one you want the width.
But be aware that this listner may run more than once.
When my application loads into an emulator or device, it renders the screen I want it to just fine, including a View with id 'graph'. Suppose I then hit the menu button, and WITHOUT selecting any menu options, hit the back button. The screen no longer shows the View 'graph'.
It is of type View_PieChart, which extends View. Here is the relevant chunk of the XML resource file:
<org.test.View_PieChart
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:id="#+id/graph"
android:background="#000"
/>
Here's the onResume() function I'm using. Again, it shows 'graph' when the application initially launched, but once another Activity is launched, then the Back button hit by the user, it fails to draw 'graph'.
protected void onResume() {
super.onResume();
int MaxCount = 100;
View_PieChart graph = (View_PieChart) findViewById(R.id.graph);
Display display = ((WindowManager)
getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
graph.setGeometry(width, width, 15, 15, 15, 15);
graph.setData(PieData, MaxCount);
}
I've combed through lots of documentation (including the activity lifecycle documentation) but have a feeling that there's something in the View "lifecycle" that I'm not understanding. Any suggestions appreciated.
Did you intend to pass "width" twice in setGeometery()?
Also, could the problem be that at the point onResume() is called, the view layouts have not been completed and so manipulating the geometery does not work as intended. The same issue exists in onCreate() too.
I've had similar problems and found the solution was to create an OnGlobalLayoutListener() that will be called when layout is complete. For example,
mTopView = (RelativeLayout)findViewById(R.id.topView);
mTopView.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener(){
#Override
public void onGlobalLayout() {
// Do here anything that relies on view dimensions being settled
}
});
I want to find the view's position on the display screen.
To do it, I use the methods such as view.getLeft() ,view.getBottom() , view.getRight() , view.getTop(). But unfortunately, all these methods are returned 0.
Is there any alternate way to find the view's positions (i.e coordinates on screen)?
My layout main.xml:
<TextView android:id="#+id/tv1"
android:layout_width="200px"
android:layout_height="30px"
android:text="welcome to" />
<TextView android:id="#+id/tv2"
android:layout_width="200px"
android:layout_height="30px"
android:text=" Make Eit solution " />
And my class has this in onCreate():
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv1 = (TextView) findViewById(R.id.tv1);
tv2 = (TextView) findViewById(R.id.tv2);
System.out.println("tv4 width:"+tv2.getWidth());
System.out.println("tv4 height:"+tv2.getHeight());
System.out.println("Right:"+tv2.getRight());
System.out.println("Left:"+tv2.getLeft());
System.out.println("Top:"+tv2.getTop());
System.out.println("Bottom:"+tv2.getBottom());
Easiest way is to get it using
View.getLocationOnScreen(); OR getLocationInWindow();
And if you want position relative to root Layout then See
Use the getLeft(), getRight(), getTop(), and getBottom(). These can be used after the view is instantiated.
the methods u have written is enough to
find the location on screen, but the place where you have written is not correct.
try to write the methods (view.getLeft(), view.getTop()... etc) in onWindowFocusChanged(boolean hasFocus) method.
for example...
**
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
System.out.println("Right:"+tv2.getRight());
System.out.println("Left:"+tv2.getLeft());
System.out.println("Top:"+tv2.getTop());
}
}
**
it will solve your issue.
You really can't get the view before hand. You may want to do an explicit using invalidate() if possible or you can check this in the onPostResume() or onResume() function.
If you're just trying things out and want to have fun with threads, this code block will put your code onto the UI thread and will wait for everything to be rendered and then display your code:
final View gv = this;
ViewTreeObserver vto = gv.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#SuppressLint("NewApi")
public void onGlobalLayout() {
gv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
tv1=(TextView)findViewById(R.id.tv1);
tv2=(TextView)findViewById(R.id.tv2);
System.out.println("tv4 width:"+tv2.getWidth());
System.out.println("tv4 height:"+tv2.getHeight());
System.out.println("Right:"+tv2.getRight());
System.out.println("Left:"+tv2.getLeft());
System.out.println("Top:"+tv2.getTop());
System.out.println("Bottom:"+tv2.getBottom());
}
This last one is pretty heavy duty lifting but it will get the job done. I usually put any lines like this in my logs(i.e. android.util.Log)
I'm not sure that you can get the position of the view before the layout phase have been done. Once the view is layed out you can use getLocationOnScreen to get the position of the view. getTop and similar only returns the position of the view in its parent.