Android ListViews Force Selection - android

I'm inexperienced with Android and working on an app that simply displays a school bell schedule in the form of a table and hopefully highlight/apply a background color to a ListView item representative of the current period.
Currently I have attempted to do so via setting a listSelector color:
From activity_bell_schedule.xml:
<ListView android:layout_height="wrap_content"
android:layout_width="0dp"
android:id="#+id/lstPeriods"
android:layout_weight=".4"
android:listSelector="#color/colorAccent"
android:divider="#color/colorPrimaryDark"
android:dividerHeight="1dp"/>
However, I then need to be able to lock/force the selection to remain as the ListView item of the current period. I tried by setting it in a function called through the onCreate function of my BellScheduleActivity class and this(I used 2 for the position for testing purposes):
From BellScheduleActivity.java:
lvp.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
System.out.println(position);
lvp.setSelection(2);
lvp.setItemChecked(2, true);
lvt.setSelection(2);
}
});
I have tried a variety of methods involving selection highlighting and selecting. If anyone has any idea what I am doing wrong or has another approach that might work, I would really appreciate it.

You can do this by setting a custom adapter to your listview. In that adapter you can define custom behavior.
In your case it would be to override the following methods in the adapter-
getItemViewType()
getViewTypeCount()
getView()
In that adapter you can define your two view types. And in getView() you can call getItemViewType() and define custom behavior.
Example for getItemViewType() is here
Another example which is similar to your question
This should solve your issue. Let me know if it works. This is like the default pattern in displaying custom listViews.
P.S. I would recommend you use RecyclerView as it is the newer(and better)ListView and is the new standard in Material Design.

Related

How can I make listview clickable when custom adapter view is used?

I know this question is asked several times and I tried to solve according the other solution but in vain. I used customAdapterView with listview. I have also set clickable in the xml. But it's not working.
My question is what's the error that listview is not being clickable?
**Another interesting matter catches my eye that if i start any id name with "list....." during findViewby resoruce id or case - the "l" alphabet automatically becomes captial. Why it happens?
The following portion is inside of onCreate method:-
uddin= getResources().getStringArray(R.array.uddin_name_array);
body=getResources().getStringArray(R.array.uddin_body_array);
prof = getResources().getStringArray(R.array.prof_name_array);
ListView listView= findViewById(R.id.uddinListView);
listView.setClickable(true);
listView.setAdapter(new MyCustomAdapter(this,R.layout.activity_list_view,uddin,prof));
listView.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent=new Intent(MainActivity.this,ReadingUddinActivity.class);
startActivity(intent);}
}
);
At last I have found the culprit in the code. It was in the xml code. My Java code worked without error. But it was not clickable because of a rating bar in the custom adapter view.
<RatingBar
android:id="#+id/ratingBar"
style="#style/Widget.AppCompat.RatingBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:numStars="2" />
When i assign the style as
style="#style/Widget.AppCompat.RatingBar"
list item prevents to become clickable.
but if i assign the style as
style="#style/Widget.AppCompat.RatingBar.Small"
or,
style="#style/Widget.AppCompat.RatingBar.Indicator"
it works fine. I don't know why the first one doesn't work. Expert may find the reasons.

Change color of an selected ListView item

i use a default android project and try to find a way to change the background color of a listview item that got selected. I know this is done via selectors. I tried to mimic the original look and behaviour coming from the holo themes and just change the color in there, but i failed. Can somebody explain to me how to get the original look and feel for listview items (longclick fade etc) and just change the color from this strange blue to something else?
What do I have to copy to my project from android sdk and where to change the selected color?
Assuming you're using a custom ArrayAdapter, you'll have to define your onClick() listener on the second parameter of your getView() method. Usually it's called convertView, but it doesn't have to.
This second parameter, speaking very vaguely, references to the layout of each row. So when you want to change the background of your row, simply add a onClickListener() on the second parameter, and change the background:
convertView.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
convertView.setBackground(your_new_background);
}
});
dude you can use custom adapter for your listview.
In custom xml files u can change everthing.
For detail example follow here
I am not sure what you asking , but watever I understood I think you want something like
listview.setOnItemClickListener(new OnItemClickListener(){
#override
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
..............................
view.setBackground("Your color");
}
});

Dynamically adding subitems to ListView in Android

I am trying to dynamically add information to a ListView. The information I am adding consists of a "Device Name" (the main item) and "MAC Address" (the sub item). An example from online is below. Note: I want to replace Item 1 with a device 1's name, sub item 1 with device 1's MAC address, and so on. This MUST be done dynamically because the list is being populated as devices are scanned for.
.
Before this is marked as a repeat, I have looked at the following questions and they have not helped me: Adding ListView Sub Item Text in Android, How to add subitems in a ListView, Adding Items and Subitems to a ListView
The conclusion I have come to through reading these questions is that I need to implement a custom ArrayAdapter and override the getView() method. I have created a custom layout with two text views in it:
cyan_list.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/main_item"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#color/cyan"/>
<TextView
android:id="#+id/sub_item"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#color/dark_cyan"/>
</LinearLayout>
I then try to create a custom ArrayAdapter in my Activity class, but I am lost as to what to put in my public View getView(final int position, View convertView, ViewGroup parent) method. Additionally, is creating a custom ArrayAdapter necessary if all I am trying to do is add a textview sub item?
The answer to your question is: NO, you don't need to create a custom ArrayAdapter if you just want to add items. I recommend, however, creating it if your layout is customized, as you'll gain so much control over the items you're displaying. You didn't add your code where you create your ArrayAdapter, but in your case I'd use this constructor. The important part is the third parameter: In your activity, you should store an ArrayList with the initial items you're adding to your ArrayAdapter, then, if you want to add a new item, you simply add it to the ArrayAdapter and call notifyDataSetChanged() on your adapter. Simply doing that, your item will be added to the layout and displayed. If you need to override the GetView method for your own ArrayAdapter, I recommend this link, it helped me understanding the whole thing.
are you searching some listview example in google like those tutorials :
http://www.vogella.com/tutorials/AndroidListView/article.html
http://www.mkyong.com/android/android-listview-example/
I think they explain step by step how to create a list adapter
You need to add getter method into your Adapter
YourAdapter ...{
List<Device> items = new ArrayList<Device>;
public List<Device> getItems(){
return items;
}
}
then change item that you need
...{
//for 1s item
Device item = getItems().get(0);
item.setTitle(macAdress)
}
and call notifyDataSetChanged for your adapter
...
yourListView.getAdapter().notifyDataSetChanged();
}
Thats it. Now you are able to change your list data.
And for your question, i think yes. Is better to create your own adapter in order to have simple possibility to exentd it later. And in your case (if you dont want to change your adapter after each title change) you deffinetly need custom one. Cheers

Android ListView with EditText focus issues [duplicate]

I've spent about 6 hours on this so far, and been hitting nothing but roadblocks. The general premise is that there is some row in a ListView (whether it's generated by the adapter, or added as a header view) that contains an EditText widget and a Button. All I want to do is be able to use the jogball/arrows, to navigate the selector to individual items like normal, but when I get to a particular row -- even if I have to explicitly identify the row -- that has a focusable child, I want that child to take focus instead of indicating the position with the selector.
I've tried many possibilities, and have so far had no luck.
layout:
<ListView
android:id="#android:id/list"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
/>
Header view:
EditText view = new EditText(this);
listView.addHeaderView(view, null, true);
Assuming there are other items in the adapter, using the arrow keys will move the selection up/down in the list, as expected; but when getting to the header row, it is also displayed with the selector, and no way to focus into the EditText using the jogball. Note: tapping on the EditText will focus it at that point, however that relies on a touchscreen, which should not be a requirement.
ListView apparently has two modes in this regard:
1. setItemsCanFocus(true): selector is never displayed, but the EditText can get focus when using the arrows. Focus search algorithm is hard to predict, and no visual feedback (on any rows: having focusable children or not) on which item is selected, both of which can give the user an unexpected experience.
2. setItemsCanFocus(false): selector is always drawn in non-touch-mode, and EditText can never get focus -- even if you tap on it.
To make matters worse, calling editTextView.requestFocus() returns true, but in fact does not give the EditText focus.
What I'm envisioning is basically a hybrid of 1 & 2, where rather than the list setting if all items are focusable or not, I want to set focusability for a single item in the list, so that the selector seamlessly transitions from selecting the entire row for non-focusable items, and traversing the focus tree for items that contain focusable children.
Any takers?
This helped me.
In your manifest :
<activity android:name= ".yourActivity" android:windowSoftInputMode="adjustPan"/>
Sorry, answered my own question. It may not be the most correct or most elegant solution, but it works for me, and gives a pretty solid user experience. I looked into the code for ListView to see why the two behaviors are so different, and came across this from ListView.java:
public void setItemsCanFocus(boolean itemsCanFocus) {
mItemsCanFocus = itemsCanFocus;
if (!itemsCanFocus) {
setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
}
}
So, when calling setItemsCanFocus(false), it's also setting descendant focusability such that no child can get focus. This explains why I couldn't just toggle mItemsCanFocus in the ListView's OnItemSelectedListener -- because the ListView was then blocking focus to all children.
What I have now:
<ListView
android:id="#android:id/list"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:descendantFocusability="beforeDescendants"
/>
I use beforeDescendants because the selector will only be drawn when the ListView itself (not a child) has focus, so the default behavior needs to be that the ListView takes focus first and draws selectors.
Then in the OnItemSelectedListener, since I know which header view I want to override the selector (would take more work to dynamically determine if any given position contains a focusable view), I can change descendant focusability, and set focus on the EditText. And when I navigate out of that header, change it back it again.
public void onItemSelected(AdapterView<?> listView, View view, int position, long id)
{
if (position == 1)
{
// listView.setItemsCanFocus(true);
// Use afterDescendants, because I don't want the ListView to steal focus
listView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
myEditText.requestFocus();
}
else
{
if (!listView.isFocused())
{
// listView.setItemsCanFocus(false);
// Use beforeDescendants so that the EditText doesn't re-take focus
listView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
listView.requestFocus();
}
}
}
public void onNothingSelected(AdapterView<?> listView)
{
// This happens when you start scrolling, so we need to prevent it from staying
// in the afterDescendants mode if the EditText was focused
listView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
}
Note the commented-out setItemsCanFocus calls. With those calls, I got the correct behavior, but setItemsCanFocus(false) caused focus to jump from the EditText, to another widget outside of the ListView, back to the ListView and displayed the selector on the next selected item, and that jumping focus was distracting. Removing the ItemsCanFocus change, and just toggling descendant focusability got me the desired behavior. All items draw the selector as normal, but when getting to the row with the EditText, it focused on the text field instead. Then when continuing out of that EditText, it started drawing the selector again.
My task was to implement ListView which expands when clicked. The additional space shows EditText where you can input some text. App should be functional on 2.2+ (up to 4.2.2 at time of writing this)
I tried numerous solutions from this post and others I could find; tested them on 2.2 up to 4.2.2 devices.
None of solutions was satisfactionary on all devices 2.2+, each solution presented with different problems.
I wanted to share my final solution :
set listview to android:descendantFocusability="afterDescendants"
set listview to setItemsCanFocus(true);
set your activity to android:windowSoftInputMode="adjustResize"
Many people suggest adjustPan but adjustResize gives much better ux imho, just test this in your case. With adjustPan you will get bottom listitems obscured for instance. Docs suggest that ("This is generally less desirable than resizing"). Also on 4.0.4 after user starts typing on soft keyboard the screen pans to the top.
on 4.2.2 with adjustResize there are some problems with EditText focus. The solution is to apply rjrjr solution from this thread. It looks scarry but it is not. And it works. Just try it.
Additional 5. Due to adapter being refreshed (because of view resize) when EditText gains focus on pre HoneyComb versions I found an issue with reversed views:
getting View for ListView item / reverse order on 2.2; works on 4.0.3
If you are doing some animations you might want to change behaviour to adjustPan for pre-honeycomb versions so that resize doesnt fire and adapter doesn't refresh the views. You just need to add something like this
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB)
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
All this gives acceptable ux on 2.2 - 4.2.2 devices.
Hope it will save people some time as it took me at least several hours to come to this conclusion.
This saved my life--->
set this line
ListView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
Then in your manifest in activity tag type this-->
<activity android:windowSoftInputMode="adjustPan">
Your usual intent
We're trying this on a short list that does not do any view recycling. So far so good.
XML:
<RitalinLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ListView
android:id="#+id/cart_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbarStyle="outsideOverlay"
/>
</RitalinLayout>
Java:
/**
* It helps you keep focused.
*
* For use as a parent of {#link android.widget.ListView}s that need to use EditText
* children for inline editing.
*/
public class RitalinLayout extends FrameLayout {
View sticky;
public RitalinLayout(Context context, AttributeSet attrs) {
super(context, attrs);
ViewTreeObserver vto = getViewTreeObserver();
vto.addOnGlobalFocusChangeListener(new ViewTreeObserver.OnGlobalFocusChangeListener() {
#Override public void onGlobalFocusChanged(View oldFocus, View newFocus) {
if (newFocus == null) return;
View baby = getChildAt(0);
if (newFocus != baby) {
ViewParent parent = newFocus.getParent();
while (parent != null && parent != parent.getParent()) {
if (parent == baby) {
sticky = newFocus;
break;
}
parent = parent.getParent();
}
}
}
});
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override public void onGlobalLayout() {
if (sticky != null) {
sticky.requestFocus();
}
}
});
}
}
this post was matching exactly my keywords. I have a ListView header with a search EditText and a search Button.
In order to give focus to the EditText after loosing the initial focus the only HACK that i found is:
searchText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// LOTS OF HACKS TO MAKE THIS WORK.. UFF...
searchButton.requestFocusFromTouch();
searchText.requestFocus();
}
});
Lost lots of hours and it's not a real fix. Hope it helps someone tough.
If the list is dynamic and contains focusable widgets, then the right option is to use RecyclerView instead of ListView IMO.
The workarounds that set adjustPan, FOCUS_AFTER_DESCENDANTS, or manually remember focused position, are indeed just workarounds. They have corner cases (scrolling + soft keyboard issues, caret changing position in EditText). They don't change the fact that ListView creates/destroys views en masse during notifyDataSetChanged.
With RecyclerView, you notify about individual inserts, updates, and deletes. The focused view is not being recreated so no issues with form controls losing focus. As an added bonus, RecyclerView animates the list item insertions and removals.
Here's an example from official docs on how to get started with RecyclerView: Developer guide - Create a List with RecyclerView
some times when you use android:windowSoftInputMode="stateAlwaysHidden"in manifest activity or xml, that time it will lose keyboard focus. So first check for that property in your xml and manifest,if it is there just remove it. After add these option to manifest file in side activity android:windowSoftInputMode="adjustPan"and add this property to listview in xml android:descendantFocusability="beforeDescendants"
Another simple solution is to define your onClickListener, in the getView(..) method, of your ListAdapter.
public View getView(final int position, View convertView, ViewGroup parent){
//initialise your view
...
View row = context.getLayoutInflater().inflate(R.layout.list_item, null);
...
//define your listener on inner items
//define your global listener
row.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
doSomethingWithViewAndPosition(v,position);
}
});
return row;
That way your row are clickable, and your inner view too :)
The most important part is to get the focus working for the list cell.
Especially for list on Google TV this is essential:
setItemsCanFocus method of the list view does the trick:
...
mPuzzleList = (ListView) mGameprogressView.findViewById(R.id.gameprogress_puzzlelist);
mPuzzleList.setItemsCanFocus(true);
mPuzzleList.setAdapter(new PuzzleListAdapter(ctx,PuzzleGenerator.getPuzzles(ctx, getResources(), version_lite)));
...
My list cell xml starts like follows:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/puzzleDetailFrame"
android:focusable="true"
android:nextFocusLeft="#+id/gameprogress_lessDetails"
android:nextFocusRight="#+id/gameprogress_reset"
...
nextFocusLeft/Right are also important for D-Pad navigation.
For more details check out the great other answers.
I just found another solution. I believe it's more a hack than a solution but it works on android 2.3.7 and android 4.3 (I've even tested that good old D-pad)
init your webview as usual and add this: (thanks Michael Bierman)
listView.setItemsCanFocus(true);
During the getView call:
editText.setOnFocusChangeListener(
new OnFocusChangeListener(View view,boolean hasFocus){
view.post(new Runnable() {
#Override
public void run() {
view.requestFocus();
view.requestFocusFromTouch();
}
});
Just try this
android:windowSoftInputMode="adjustNothing"
in the
activity
section of your manifest.
Yes, it adjusts nothings, which means the editText will stay where it is when IME is opening. But that's just an little inconvenience that still completely solves the problem of losing focus.
In my case, there is 14 input edit text in the list view. The problem I was facing, when the keyboard open, edit text focus lost, scroll the layout, and as soon as focused view not visible to the user keyboard down. It was not good for the user experience. I can't use windowSoftInputMethod="adjustPan". So after so much searching, I found a link that inflates custom layout and sets data on view as an adapter by using LinearLayout and scrollView and work well for my case.

How to manage list views Checkboxes Automatically checking?

This is my list i want My problem is when i scroll list view then the check boxes(which are the items of this List ) are automatically checked
ex - if i checked first then 4 automatically being checked.
My first goal:
1. want to stretch my list to full i will wrap it into Scrollview how
2. i can prevent it to automatically checked
.
<ListView
android:id="#+id/ListViewProducts"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_column="0"
android:layout_span="2"
android:clickable="true"
android:isScrollContainer="true"
android:saveEnabled="true"
android:scrollbarAlwaysDrawVerticalTrack="true"
android:scrollbarSize="10sp"
android:scrollbars="vertical" >
</ListView>
Create your own BaseAdapter.
Keep in mind, that ALL views in your listview you see are temporary. They will be recycled when you'll scroll away. The reason is - you can have >9000 elements in your list. So, the way you create views must depend on some kind of (!) data.
Here is nince tutorial on how to create your own list.
Make X-th checkbox depend on X-th boolean in the list. A bit confusing first time I know, but this is the best way.
class MyAdapter extends BaseAdapter{
List<boolean> myCheckBoxes;
boolean getItem(int arg0){
return myCheckBoxes.get(arg0);
}
View getView(int arg0, View arg1, ViewGroup arg2){
...
...//See article
myView.setChecked(getItem(arg0));
...
return myView;
}
And in your activity
ListView myListView;
...
myListView.setAdapter(new MyAdapger(...));
You can't put a listview into a scrollview, two views scrolling in the same direction will not work nicely. Just put the listview in your non scrolling layout (frame- , list-, relativelayout).
Use an Adapter that sets every listview's row's views according to the data to be displayed.
ListView already extends ScrollView and doesn't need to have another one to surround it.
try looking at this post on creating custom listView items. you can implement a checkBox in them and make is have android:checked="false"
ListVew already extends ScrollView no need to implement it on ListView
for AutoCheck follow this link:
Check box checked Automatically in listview when scrolling the list.
There's no need to implement scrollview in listview becoz it is already extends to scrollview.
I think your listview is not able to handle the recycling of items properly.So to solve this problem go through the below link.
Getting an issue while checking the dynamically generated checkbox through list view

Categories

Resources