I'm trying to scroll to a given layout in a ScrollView. My XML is basically composed of a ScrollView implementing various RelativeLayout and I want to programatically scroll to a given one.
I have the following code in my Activity's onCreate method :
// Defining my view
sv = (ScrollView)findViewById(R.id.reward_scroll_view);
// Get Layout's id from intent
Bundle extras = getIntent().getExtras();
if (extras != null) {
idToScroll = extras.getInt("uiToScroll");
sv.post(new Runnable() {
public void run() {
// Scroll to the passed element
RelativeLayout layout = (RelativeLayout) findViewById(idToScroll);
sv.smoothScrollTo(0, layout.getTop());
}
});
}
The "auto-scroll" to a given anchor is working but there is no "smooth" effect, just a raw scroll to the layout. What am I missing ?
You are overriding post method of view.
Scroll view not working smoothly with in UI Thread or Post
Look at this question
I resolved my problem thanks to Aamir's comment, here is how my final code looks like :
Bundle extras = getIntent().getExtras();
if (extras != null) {
// Get Layout's id from intent
idToScroll = extras.getInt("uiToScroll");
layout = (RelativeLayout) findViewById(idToScroll);
// Start 1 second timer
new CountDownTimer(1000, 20) {
public void onTick(long millisUntilFinished) {
// Nothing...
}
// When over, start smoothScroll
public void onFinish() {
sv.smoothScrollTo( 0, layout.getTop() );
}
}.start();
}
My view may have just need some delay to display the scroll effect properly.
Related
In my app, I need to show and hide widgets like button and textview at a certain time.
and how I am doing is as the following:
private void hideviews() {
image.setVisibility(View.GONE); ///ImageView
title1.setVisibility(View.GONE);///TextView
title2.setVisibility(View.GONE);///TextView
title3.setVisibility(View.GONE);///TextView
title4.setVisibility(View.GONE);///TextView
title5.setVisibility(View.GONE);///TextView
}
private void showviews() {
image.setVisibility(View.VISIBLE);
title1.setVisibility(View.VISIBLE);///TextView
title2.setVisibility(View.VISIBLE);///TextView
title3.setVisibility(View.VISIBLE);///TextView
title4.setVisibility(View.VISIBLE);///TextView
title5.setVisibility(View.VISIBLE);///TextView
}
I don't think this is the correct way to do this.
Because I don't know how many widgets there will be.
Any guidance on how to correctly show widgets is really appreciated.
Get the reference to root layout, iterate through the childs, check if the view at certain index is instance of EditText(or View that you dont need to hide), if not hide it
RelativeLayout root = findViewById(R.id.root)
for(i=0,i<root.getChildCount()-1,i++){
if(! (root.getChildAt(i) instance of EditText)){
root.getChildAt(i).setVisibility(View.GONE)
}
}
Since you don't know how many testviews will be attached, then I believe that the best approach will be to:
get the reference of the parent view group (that contains all the
textviews),
loop through all the childs using getChildAt,
verify whether the object is an instance of TextView/ImageView and if so set its visibility according to your logic
Instead of hiding every widget separately hide the root layout.
RelativeLayout rootLayout;
rootLayout= (RelativeLayout) findViewById(R.id.root_layout);
and use something like this to control the visibility.
public void setLayoutInvisible() {
if (rootLayout.getVisibility() == View.VISIBLE) {
rootLayout.setVisibility(View.GONE);
}
}
public void setLayoutVisible() {
if (rootLayout.getVisibility() == View.GONE) {
rootLayout.setVisibility(View.VISIBLE);
}
}
Make an array of all the views that you want to show/hide:
View[] views = {image, title1, title2, title3, title4, title5};
and then use this to hide them:
for (View view : views) {
view.setVisibility(View.GONE);
}
and use this to show them:
for (View view : views) {
view.setVisibility(View.VISIBLE);
}
although you can combine the 2 code parts in a single procedure:
void fixViews(int state) {
for (View view : views) {
view.setVisibility(state);
}
}
and call it:
fixViews(View.GONE); or fixViews(View.VISIBLE);
I'm new to Android and I'm trying to find out how to do that:
- I have an activity with a ScrollView and inside it I have a LinearLayout (R.id.my_layout)
- I nedd to add TextView programmatically so I'm doing this:
I load the main XML layout via seContentView, I refer to my LinearLayout inside the ScrollView as "mLayout" and so on.
I load a list of names from a file and with a function called populateList()I do:
private void populateList() {
try {
for (final String team : mTeams) {
rCount++;
addRow(team);
}
}
The addRow() method just create a new LinearLayout (mRow), a TextView, 2 Button, add the TextView and the 2 Buttons to the LinearLayout, and then I use addView to add the new mRow to the mLayout.
Everything is working fine, but the ScrollView is shown only when i finished creating the list (so when the populateList() ends). What I would like to do is to show the rows one by one in sequence to give the activty a better look and a bit of animation.
Is there a way to do this?
I hope i was able to explain it :-)
Thank you
new Thread(new Runnable() { // i am creating the new thread
#Override
public void run() {
// so call populateList() function here
}
}).start();
and for your addRow(String string) method the place you call View.addView(); edit it this way and place the following code in your addRow(String string) method
View.post(new new Runnable() {// view here is mlayout the scrollView.
#Override
public void run() {
mlayout.addView(yourview); // note yourview should be final,
//eclipse might help you with that
}
});
remember to declare mlayout globally, so you do not have to attach final
This is my function which will fetch some 1300 record from SQLite database and draw a series of text view inside the table layout. But when this function starts executing full application is not responding for some time. Table layout is again inside a Scroll View.
Basically I want it to load in back ground.so that remaining application is still responsive
public void LoadAlarmNotifications() {
int SerNo = 0 ;
TextView SerNoTxtVw;
TextView AlarmTxtVw;
TextView TimeOccuredTxtVw;
TextView UploadTxtTxtVw;
Notificationtablelayout.setGravity(Gravity.CENTER);
pastEvent_tbleList = oDatabaseHandler.FetchPastEventDetails(sDiagnosisID);
if(pastEvent_tbleList != null)
{
for(Pastevents_tble PEvents_tble: pastEvent_tbleList)
{
final TableRow row = new TableRow(this.getApplicationContext());
nAlarmType = PEvents_tble.GetAlarmID();
nRowID = PEvents_tble.GetEventNo();
SerNo = PEvents_tble.GetEventNo();
SetAlarmType(nAlarmType); // Set Alarm
tAlarmTime = PEvents_tble.GetStrtTime();
sUploadStatus = PEvents_tble.GetUploadStatus();
row.setId(nRowID);
SerNoTxtVw =new TextView(this.getApplicationContext());
AlarmTxtVw =new TextView(this.getApplicationContext());
TimeOccuredTxtVw=new TextView(this.getApplicationContext());
UploadTxtTxtVw =new TextView(this.getApplicationContext());
SerNoTxtVw.setText(Integer.toString(SerNo));
SerNoTxtVw.setWidth(80);
SerNoTxtVw.setHeight(40);
SerNoTxtVw.setGravity(Gravity.CENTER);
SerNoTxtVw.setPadding(2, 2,2,2);
SerNoTxtVw.setTextColor(Color.parseColor("#FFAADDFF"));
row.addView(SerNoTxtVw);
AlarmTxtVw.setText(sAlarmName);
AlarmTxtVw.setWidth(100);
AlarmTxtVw.setHeight(40);
AlarmTxtVw.setGravity(Gravity.LEFT);
AlarmTxtVw.setPadding(2,2,2,2);
// AlarmTxtVw.setBackgroundColor(Color.LTGRAY);
row.addView(AlarmTxtVw);
TimeOccuredTxtVw.setText(tAlarmTime);
TimeOccuredTxtVw.setWidth(140);
TimeOccuredTxtVw.setHeight(40);
TimeOccuredTxtVw.setGravity(Gravity.CENTER);
TimeOccuredTxtVw.setPadding(2,2,2,2);
// TimeOccuredTxtVw.setBackgroundColor(Color.LTGRAY);
row.addView(TimeOccuredTxtVw);
UploadTxtTxtVw.setText(sUploadStatus);
if(sUploadStatus.equals("Y")){
UploadTxtTxtVw.setText("✔");
UploadTxtTxtVw.setTextColor(Color.parseColor("#FF00FF00"));
}
else if(sUploadStatus.equals("N")){
UploadTxtTxtVw.setText("X");
UploadTxtTxtVw.setTextColor(Color.parseColor("#FFFF0000"));
}else
{
UploadTxtTxtVw.setText("✔");
UploadTxtTxtVw.setTextColor(Color.parseColor("#FFAADDFF"));
}
UploadTxtTxtVw.setWidth(100);
UploadTxtTxtVw.setHeight(40);
UploadTxtTxtVw.setGravity(Gravity.CENTER);
UploadTxtTxtVw.setPadding(2,2,2,2);
// UploadTxtTxtVw.setBackgroundColor(Color.LTGRAY);
row.addView(UploadTxtTxtVw);
Notificationtablelayout.addView(row);
nProgressCounter++;
row.setOnClickListener(new OnClickListener() {
#Override
public void onClick(final View SelectedRowVw) {
if(!bSwitchPopOpen)
{
}
});
}
LoadingTxtView.setVisibility(View.GONE);
bEpisodeLoad = true;
} else
{
bEpisodeLoad = true;
LoadingTxtView.setText("No Snapshot available...");
}
}
pastEvent_tbleList size is 1335. Any idea how to optimize this. Instead of text view is there any other light control?
You should use the Loader pattern to do this so that you only load content that the user will actually see, and you should also reuse the text views on the screen. This is what ListView / CursorLoader were created to solve, so you really ought to reuse these components if at all possible.
You should use listview, because it loads visible area so application will not stop doing calculations and you can scroll up and down and see your texviews
How can I programmatically scroll to a specific position in a ListView?
For example, I have a String[] {A,B,C,D....}, and I need to set the top visible item of the ListView to the index 21 of my String[].
For a direct scroll:
getListView().setSelection(21);
For a smooth scroll:
getListView().smoothScrollToPosition(21);
For a SmoothScroll with Scroll duration:
getListView().smoothScrollToPositionFromTop(position,offset,duration);
Parameters
position -> Position to scroll to
offset ---->Desired distance in pixels of position from the top of the view when scrolling is finished
duration-> Number of milliseconds to use for the scroll
Note: From API 11.
HandlerExploit's answer was what I was looking for, but My listview is quite lengthy and also with alphabet scroller. Then I found that the same function can take other parameters as well :)
Edit:(From AFDs suggestion)
To position the current selection:
int h1 = mListView.getHeight();
int h2 = listViewRow.getHeight();
mListView.smoothScrollToPositionFromTop(position, h1/2 - h2/2, duration);
Put your code in handler as follows,
public void timerDelayRunForScroll(long time) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
try {
lstView.smoothScrollToPosition(YOUR_POSITION);
} catch (Exception e) {}
}
}, time);
}
and then call this method like,
timerDelayRunForScroll(100);
CHEERS!!!
The Listview scroll will be positioned to top by default, but want to scroll if not visible then use this:
if (listView1.getFirstVisiblePosition() > position || listView1.getLastVisiblePosition() < position)
listView1.setSelection(position);
I have set OnGroupExpandListener and override onGroupExpand() as:
and use setSelectionFromTop() method which
Sets the selected item and positions the selection y pixels from the top edge of the ListView. (If in touch mode, the item will not be selected but it will still be positioned appropriately.) (android docs)
yourlist.setOnGroupExpandListener (new ExpandableListView.OnGroupExpandListener()
{
#Override
public void onGroupExpand(int groupPosition) {
expList.setSelectionFromTop(groupPosition, 0);
//your other code
}
});
If someone looking for a similar functionality like Gmail app,
The Listview scroll will be positioned to top by default. Thanks for the hint.
amalBit.
Just subtract it. That's it.
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
int h1 = mDrawerList.getHeight();
int h2 = header.getHeight();
mDrawerList.smoothScrollToPosition(h2-h1);
}
}, 1000);
If you want to jump directly to the desired position in a listView just use
listView.setSelection(int position);
and if you want to jump smoothly to the desired position in listView just use
listView.smoothScrollToPosition(int position);
Handling listView scrolling using UP/ Down using.button
If someone is interested in handling listView one row up/down using button. then.
public View.OnClickListener onChk = new View.OnClickListener() {
public void onClick(View v) {
int index = list.getFirstVisiblePosition();
getListView().smoothScrollToPosition(index+1); // For increment.
}
});
This is what worked for me. Combination of answers by amalBit & Melbourne Lopes
public void timerDelayRunForScroll(long time) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
try {
int h1 = mListView.getHeight();
int h2 = v.getHeight();
mListView.smoothScrollToPositionFromTop(YOUR_POSITION, h1/2 - h2/2, 500);
} catch (Exception e) {}
}
}, time);
}
and then call this method like:
timerDelayRunForScroll(400);
-If you just want the list to scroll up\dawn to a specific position:
myListView.smoothScrollToPosition(i);
-if you want to get the position of a specific item in myListView:
myListView.getItemAtPosition(i);
-also this myListView.getVerticalScrollbarPosition(i);can helps you.
Good Luck :)
You need two things to precisely define the scroll position of a listView:
To get the current listView Scroll position:
int firstVisiblePosition = listView.getFirstVisiblePosition();
int topEdge=listView.getChildAt(0).getTop(); //This gives how much the top view has been scrolled.
To set the listView Scroll position:
listView.setSelectionFromTop(firstVisiblePosition,0);
// Note the '-' sign for scrollTo..
listView.scrollTo(0,-topEdge);
it is easy
list-view.set selection(you pos);
or you can save your position with SharedPreference and when you start activity
it get preferences and setSeletion to that int
I found this solution to allow the scroll up and down using two different buttons.
As suggested by #Nepster I implement the scroll programmatically using the getFirstVisiblePosition() and getLastVisiblePosition() to get the current position.
final ListView lwresult = (ListView) findViewById(R.id.rds_rdi_mat_list);
.....
if (list.size() > 0) {
ImageButton bnt = (ImageButton) findViewById(R.id.down_action);
bnt.setVisibility(View.VISIBLE);
bnt.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(lwresult.getLastVisiblePosition()<lwresult.getAdapter().getCount()){
lwresult.smoothScrollToPosition(lwresult.getLastVisiblePosition()+5);
}else{
lwresult.smoothScrollToPosition(lwresult.getAdapter().getCount());
}
}
});
bnt = (ImageButton) findViewById(R.id.up_action);
bnt.setVisibility(View.VISIBLE);
bnt.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(lwresult.getFirstVisiblePosition()>0){
lwresult.smoothScrollToPosition(lwresult.getFirstVisiblePosition()-5);
}else{
lwresult.smoothScrollToPosition(0);
}
}
});
}
I was looking through the WindowManager's API but I couldn't find a way to make the window disappear after a certain period of time. My desired functionality is to initially make the window pop up, wait until timeout and then disappear/delete itself.
ViewManager.removeView(View v)
try it:
new Handler().postDelayed(new Runnable(){
public void run() {
yourParentView.removeView(childView);
}
}, TIME);
Try adding and using this method:
/**
* Simple method that will take any view class and remove it from it's parent
* #param viewToRemove the view you want to remove from its parent
*/
private void removeViewFromItsParent(View viewToRemove){
if (viewToRemove == null || viewToRemove.getParent() == null){
Log.w("tag", "view or parent is null, no-operation");
return;
}
ViewGroup viewGroupParent = (ViewGroup) viewToRemove.getParent();
viewGroupParent.removeView(viewToRemove);
}
Something like: removeViewFromItsParent(view);
More info here about ViewGroup including its subclasses and what methods you can use (there are a few remove calls that do slightly different things) : http://developer.android.com/reference/android/view/ViewGroup.html