I have to set focus on listview item. ListView consist of TextView.
point where i want to set focus on listview item, at that point i have the position of that item.
I have tried setSelectio(pos), where pos is the position of listview item, but this results in setting the position of item at position on the top of the screen.
please suggest me how to proceed.
builder.setPositiveButton(R.string.save,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Log.d("#gaurav", "changeText is not null");
if (null != changeText) {
Log.d("#gaurav", "changeText is not null");
if (!(changeText.getText().toString().equalsIgnoreCase(""))) {
myList
.set(pos, changeText.getText()
.toString());
adapter.notifyDataSetChanged();
setListAdapter(adapter);
}
} else {
Log.d("#gaurav", "changeText is null");
}
getListView().setFocusableInTouchMode(true);
getListView().setSelection(pos);
getListView().requestFocus();
}
});
I think you want to highlight a particular list item based on your requirement. So you are not able to set the focus if the item is not visible in the screen. Am I right ? If that is your problem you can use following method public void smoothScrollToPosition (int position)
Added in API level 8 to scroll to that particular position and then use setSelection() method
If you want to set focus/color on particular index of ListView, you should try this, it works well.
list.post(new Runnable() {
#Override
public void run() {
list.setSelected(true);
list.getChildAt(0).setBackgroundColor(Color.BLACK);
list.getChildAt(1).setBackgroundColor(Color.BLUE);
firstListItemPosition = firstListItemPosition +1;
Log.v("firstListItemPosition", "firstListItemPosition ");
}
});
firstListItemPosition = list.getFirstVisiblePosition();
Related
I have created a horizontal recyclerview list. below is the image I have attached.
problem is that I have to change bulb state when everytime user clicked that row from off state to on state and on state to off state.
How do I implement this logic? please help me to find out the solution.
i want to change light color according to user clicks, if he clicks on then it should change its color for that row and vise versa
public void onClick(View view, int position) {
//toast("clicked" + position );
if (!lightClicked){
ImageView lightPopUp = view.findViewById(R.id.row_light_thumbnail);
DrawableCompat.setTint(lightPopUp.getDrawable().mutate(), ContextCompat.getColor(getContext(), R.color.white));
//toast("light on");
lightClicked = true;
}else {
ImageView lightPopUp = view.findViewById(R.id.row_light_thumbnail);
//toast("light off");
DrawableCompat.setTint(lightPopUp.getDrawable().mutate(), ContextCompat.getColor(getContext(), R.color.colorAccent));
lightClicked = false;
}
//View view1 = mLayoutManager.findViewByPosition(position);
}
Dont directly do this change as the recycler view's cells are reused and it wont work as expected, so instead apply the change in the list you are using. You can add a boolean variable in the model class of the list you use to populate the recycler view, and than on its click you can change the boolean's value and call notifydatasetchange on the adapter, and in bind view you should keep an If else condition based on that boolean for the Bulb's image
ie. if true set one image if false set another
declare this :
int selectedPosition=-1;
inside onBindViewHolder:
public void onBindViewHolder(FiltersAdapter.ViewHolder holder, int position) {
if(selectedPosition==position)
holder.itemView.setImageResource(R.drawable.higlihgt_image);
else
holder.itemView.setImageResource(R.drawable.normal_image);
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
selectedPosition=position;
notifyDataSetChanged();
}
});
}
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 have an Activity containing a ViewPager that displays N fragments. Each fragment is showing the properties of an object from an ArrayList in my ViewPager's custom adapter (extends FragmentStatePagerAdapter).
The fragment has (among other things) a button that should remove the currently displayed fragment and scroll to the next one with setCurrentItem(position, true) so that if the user scrolls back, the previous item is gone. I do so by using something like this (simplified):
deleteButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
MyActivity parentActivity = (MyActivity)getActivity();
// First, scroll to next item (smoothly)
parentActivity.pager.setCurrentItem(parentActivity.pager.getCurrentItem()+1, true);
// Database stuff...
doSomeDBOperations();
// Method in Activity that removes the current object (I believe this method is working fine and yes, it calls notifyDataSetChanged())
parent.removeObject(currentObject);
}
});
This has the desired behavior as the object represented by the fragment whose delete button was pressed gets removed and the viewpager goes to the next page.
My problem is that the ViewPager doesn't scroll smoothly but rather "jumps instantly" to the next fragment. If I comment the removeObject() call, the smooth scroll works (but the item isn't removed). I believe it's has something to do with the removeObject() being called before the setCurrentItem() has finished the smooth scrolling animation?
Any ideas on how to fix this and achieve item removal + smooth scroll? If my assumption is correct, how can I make sure I get the smooth scroll to finish before removing the object?
EDIT 1:
My assumption seems correct. If I put the parent.removeObject(currentObject) inside
// ...inside the previously shown public void onClick(View v)...
confirm.postDelayed(new Runnable() {
#Override
public void run() {
// Method in Activity that removes the current object (I believe this method is working fine and yes, it calls notifyDataSetChanged())
parent.removeObject(currentObject);
}
}, 1000);
so that the removeObject() call waits for a second, it works as expected: scroll to the next item, remove the previous. But this is a very ugly workaround so I'd still like a better approach.
EDIT 2:
I figured out a possible solution (see below).
I ended up overriding the
public void onPageScrollStateChanged(int state)
method:
Whenever the user presses the delete button in the fragment, the listener sets a bool in the current item (flagging it for deletion) and scrolls to the next one.
When the onPageScrollStateChanged detects that the scroll state changed to ViewPager.SCROLL_STATE_IDLE (which happens when the smooth scroll ends) it checks if the previous item was marked for deletion and, if so, removes it from the ArrayList and calls notifyDataSetChanged().
By doing so, I've managed to get the ViewPager to smoothly scroll to the next position and delete the previous item when the "delete" button is pressed.
EDIT: Code snippet.
#Override
public void onPageScrollStateChanged(int state)
{
switch(state)
{
case ViewPager.SCROLL_STATE_DRAGGING:
break;
case ViewPager.SCROLL_STATE_IDLE:
int previousPosition = currentPosition - 1;
if(previousPosition < 0){
previousPosition = 0;
}
MyItem previousItem = itemList.get(previousPosition);
if(previousItem.isDeleted())
{
deleteItem(previousItem);
// deleteItem() Does some DB operations, then calls itemList.remove(position) and notifyDataSetChanged()
}
break;
case ViewPager.SCROLL_STATE_SETTLING:
break;
}
}
Have you tried ViewPager.OnPageChangeListener?
I would call removeObject(n) method in OnPageChangeListener.onPageSelected(n+1) method.
I did something different that works smoothly. The idea is to to remove the current item with animation (setting its alpha to 0), then translating horizontally the left or right item (with animation) to the now invisible item position.
After the animation is complete, I do the actual data removal and notfyDataSetChanged() call.
This remove() method I put inside a subclass of ViewPager
public void remove(int position, OnViewRemovedListener onViewRemovedListener) {
final int childCount = getChildCount();
if (childCount > 0) {
View toRemove = getChildAt(position);
int to = toRemove.getLeft();
final PagerAdapter adapter = getAdapter();
toRemove.animate()
.alpha(0)
.setDuration(getResources().getInteger(android.R.integer.config_shortAnimTime))
.setListener(new SimpleAnimatorListener() {
#Override
public void onAnimationEnd(Animator animation) {
if (childCount == 1) {
if (onViewRemovedListener != null) onViewRemovedListener.onRemoved(position, -1);
if (adapter!= null) adapter.notifyDataSetChanged();
}
}
})
.start();
if (childCount > 1) {
int newPosition = position + 1 <= childCount - 1 ? position + 1 : position - 1;
View replacement = getChildAt(newPosition);
int from = replacement.getLeft();
replacement.animate()
.setInterpolator(new DecelerateInterpolator())
.setDuration(getResources().getInteger(android.R.integer.config_mediumAnimTime))
.translationX(to - from)
.setListener(new SimpleAnimatorListener() {
#Override
public void onAnimationEnd(Animator animation) {
if (onViewRemovedListener != null) onViewRemovedListener.onRemoved(position, newPosition);
if (adapter!= null) adapter.notifyDataSetChanged();
}
})
.start();
}
}
}
public interface OnViewRemovedListener {
void onRemoved(int position, int newPosition);
}
I have a ListActivity and In my list I have highly complex listitems with multiple ImagesViews TextViews, and Buttons. When I click a button i want to edit some of the textviews and change some background colors. My implementation works but only if the button that I click is within the first row visible. I'm using getChildAt() to grab one of the visible rows but I need to know which one to grab.
public void onClick(View v){
System.out.println("Something got clicked");
if(v.getId() == R.id.lovebutton){
MainListItem i = mainAdapter.getItem(listView.getFirstVisiblePosition());
i.loved=true;
i.loves++;
View view;
view = listView.getChildAt(0);
//view = listView.getChildAt(1);
((TextView) view.findViewById(R.id.lovecount)).setText(String.valueOf(i.loves));
view.findViewById(R.id.lovebutton).setBackgroundColor(Color.parseColor(i.brandLoveColor));
((ImageView)view.findViewById(R.id.lovebutton)).setImageResource(R.drawable.lovewhite);
}}
There are a lot of ways in which you can do this. Saving the states in the pojo, updating them in onClick and calling #notifyDataSetChanged().
Alternatively,
You can add the position as a tag to the button in getView of the adapter. In OnClick you can get the tag. This way you will know which position the button belongs to.
With a little help from Joe - Android: Access child views from a ListView
public void onClick(View v){
System.out.println("Something got clicked");
if(v.getId() == R.id.lovebutton){
int wantedPosition = Integer.parseInt(view.getTag());
int firstPosition = listView.getFirstVisiblePosition() - listView.getHeaderViewsCount(); // This is the same as child #0
int wantedChild = wantedPosition - firstPosition;
// Say, first visible position is 8, you want position 10, wantedChild will now be 2
// So that means your view is child #2 in the ViewGroup:
if (wantedChild < 0 || wantedChild >= listView.getChildCount()) {
Log.w(TAG, "Unable to get view for desired position, because it's not being displayed on screen.");
return;
}
// Could also check if wantedPosition is between listView.getFirstVisiblePosition() and listView.getLastVisiblePosition() instead.
View wantedView = listView.getChildAt(wantedChild);
MainListItem i = mainAdapter.getItem(wantedPosition);
i.loved=true;
i.loves++;
((TextView) view.findViewById(R.id.lovecount)).setText(String.valueOf(i.loves));
view.findViewById(R.id.lovebutton).setBackgroundColor(Color.parseColor(i.brandLoveColor));
((ImageView)view.findViewById(R.id.lovebutton)).setImageResource(R.drawable.lovewhite);
}
}
In a listView to get the clicked row , You have to use "OnItemClickListener".
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int pos, long arg3) {
HashMap<String, String> o = (HashMap<String, String>) lv.getItemAtPosition(pos);
System.out.println(pos);//This will return your position
}
});
I have a view that contains a ListView which is bound to a cursor adapter. When The cursor content change I want to keep the ListView at the top then in my custom cursor adapter I added :
#Override
protected void onContentChanged() {
// ...
myListView.scrollTo(0, 0);
}
but this doesn't work. Then I read somewhere to queue this action like this :
myListView.post(new Runnable() {
public void run() {
myListView.scrollTo(0, 0);
}
});
but this doesn't work either.
How can I keep the ListView at the top when its content changes?
EDIT:
Just for try, I added a button and called scrollTo() in its onClickListener and it didn't work! What am I missing ?
Instead of scrollTo, try setSelection(0) to get to the top position of list view.
i made functions that could be useful for others for listview scrolling, they work for me in every android version, emulator and device, here itemheight is the fixed height of view in the listview.
int itemheight=60;
public void scrollToY(int position)
{
int item=(int)Math.floor(position/itemheight);
int scroll=(int) ((item*itemheight)-position);
this.setSelectionFromTop(item, scroll);// Important
}
public void scrollByY(int position)
{
position+=getListScrollY();
int item=(int)Math.floor(position/itemheight);
int scroll=(int) ((item*itemheight)-position);
this.setSelectionFromTop(item, scroll);// Important
}
public int getListScrollY()
{
try{
//int tempscroll=this.getFirstVisiblePosition()*itemheight;// Important
View v=this.getChildAt(0);
int tempscroll=(this.getFirstVisiblePosition()*itemheight)-v.getTop();// Important
return tempscroll;
}catch(Exception e){}
return 0;
}
ListView's scrollTo applies to the ListView it self as a View
setSelection(0) does the trick because it applies to the listview's adapter