I have a view (custom drawn) added with getWindowManager().addView() and later I'm modifiying the LayoutParameters of it (changing x & width) and call getWindowManager().updateViewLayout(). This works but I am getting two screen refreshes, first one only moves the whole thing according to the new x and later one scales it according to the new width. Any ideas about why is this happening even though I only call updateViewLayout just one time with the new layout parameters?
FYI: onDraw method of the custom drawn view mentioned here is also called only one time by the system during this process.
Try:
runOnUiThread(new Runnable() {
public void run() {
view.updateViewLayout();
}
});
http://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)
If it doesn't work, check this:
How to move a view in Android?
Are you doing this?
try to do :
view.post(new Runnable() {
public void run() {
view.updateViewLayout();
}
});
updateViewLayout is an a method that can be overriden by your custom ViewGroup and in this overrided method you can implement all what your want to change.
Maybe you do something wrong in it?
Or also maybe you have to implement this code in UiThread like in other questions. - In this case when you change your parameters asynchronously with first call of drawing function by system you method maybe can change only one parameter and on second call the second parameter will be also changed.
Related
I have a button called panel_close in my java code. In the setOnclickListener method I update the visibility of some other views. However, it seems sometimes the code does not update the visibility of the panels properly. Here is the code
panel_close.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
View temp=findViewById(R.id.show_panel);
temp.startAnimation(window_close);
temp.setVisibility(View.GONE);
compass.setVisibility(View.VISIBLE); // compass is defined as a field. Sometimes the code does not make this view visible
stats.setVisibility(View.VISIBLE); // stats is defined as a field. Sometimes the code does not make this view visible
control.setVisibility(View.VISIBLE); // control is defined as a field. Sometimes the code does not make this view visible
loadAllList(); // this is an AsyncTask
loadAllpins(); // this is an AsyncTask
}
});
Any comment will be appreciated.
You should look at running these changes on the UI thread to make sure that the modification are visible to the UI:
Android - using runOnUiThread to do UI changes from a thread
You should give a detailed info about your variables first and this could be happening because you are making the layout or something like that invisible or gone, which the children are inside of. This will cause them to remain invisible.
I learned this trick on Android 50 hacks ,but I don't know why this method works .Does anybody have a clue ,I was really confused.
onCreate(Bundle savedInstance){
setContentView(R.id.content);
final View view = findViewById(R.id.need_width_height);
view.post(new Runnable(){
public void run(){
Log.d(TAG,view.getWidth()+"," + view.getHeight());
}
})
From the docs:
Causes the Runnable to be added to the message queue. The runnable
will be run on the user interface thread.
This means whatever you place in the run() method of the Runnable does not run immediately. And when you say it works I assume you mean it returns valid values for the View's height and width which if it's the case, may be more fortuitous than anything else. Your technique relies on the Runnable being executed after the View has been assigned its size but there is no guarantee that this will occur (as far as I can see in the documentation.)
If its View width and size you require then use the onSizeChanged() method.
I need to set the firstVisibleItem. right now when I use smoothScrollToPositionFromTop there seems to be some visible scrolling (of course). I am drawing a blank on what the alternative method is. I have used it before, but I just can't seem to find it. Basically instead of smooth scrolling, it "instantaneously" sets the position that I select plus whatever offset I pass it. Does anyone remember which method does this? It's something like
listView.setAsTop(position, offset)
Use AbsListView#setSelection(int position):
new Handler().post(new Runnable() {
#Override
public void run() {
listView.setSelection(position);
}
});
Make sure listView and position are member variables or declared as final.
As mentioned here, Android's GridView.scrollTo() doesn't work. The method the solution mentioned, setSelectedPosition, doesn't seem to exist in GridView
smoothScrollToPosition does work, but I really don't want the animation.
For context, I have a CursorAdapter-backed GridView, and I want the view to "reset", i.e. scroll to the top, when I change the cursor.
I've been using setSelection(int position) for this, and it seems to be working just fine. To scroll to the top, just use 0 for position.
From the docs:
If in touch mode, the item will not be selected but it will still be positioned appropriately.
Edit:
Added code to post setSelection as a Runnable:
albumsView.post(new Runnable() {
#Override
public void run() {
albumsView.setSelection(0);
}
});
I have found that in order to reliably use gridView.setSelection(index), I have to first call gridView.setAdapter() (even if the adapter has already been set and has not changed). Like so:
gridView.setAdapter(gridAdapter);
gridView.setSelection(index);
I'm trying to move a ball on canvas. a and b are similar to x,y coordinate positions. Any way from my code im trying to get different values dynamically. The a,b are global variables. But it seems that "invalidate()" or the refreshing of screen only happens afer end of the whole loop. Do you know why?. And if i have to build this on another thread please suggest me with some simple codes.
private void shootBall(){
while (a>b){
a = getPositionX();
b = getPositionY();
invalidate();
}
}
}
I think it's more correct to say that you can call invalidate() from within a loop, but that that invalidation will not be handled (the canvas won't be redrawn) until after your loop is complete. The problem is that you are calling invalidate on the same thread (the UI toolkit thread) as the one that would call your onDraw() method. So unless/until you hand control back to the toolkit, it cannot possibly do the rendering. So your invalidate() call does actually invalidate the view ... but the view won't be redrawn until after your loop completes and your function returns.
It is more correct to change the position in some function that is called via some timer (which is essentially what the animation classes do). In that function, you would change the values, invalidate() appropriately, and return. Then the toolkit re-renders the scene and your function will get future callbacks and update the position accordingly.
do it like this, and use postInvalidate() instead:
private void shootBall(){
new Thread(new Runnable() {
public void run() {
while (a>b){
a = getPositionX();
b = getPositionY();
postInvalidate();
}
}
}).start();
}
edit: but as mentioned before, don't assume that the invalidate redraws the screen, it marks it as to-be-redrawn and the UI thread will get around to it.
You can put invalidate() at the end of onDraw() like in this example: How can I use the animation framework inside the canvas?
However this works well on some devices while bottlenecks and slows down on other.
To use a thread and SurfaceView go through all of these tutorials: http://www.droidnova.com/playing-with-graphics-in-android-part-i,147.html
UI cant be modified form any new thread..you should use invalidate() in the same thread where your view