I have an app that's getting information from an API request and then displaying a list of devices. After several hours of combing through documentation, I cannot figure out how to format the View that is created from the ArrayAdapter. Essentially, if the device has an error, I want to display a red circle to the right of the button and display a green button if there is no error.
deviceList is the name of a ListView that I am trying to display my list of buttons inside of. deviceNames is an array of strings that contains the names of the devices.
The TextViews that are created are also clickable, which is what the onItemClickListener is handling. This section works, but I wanted to leave it in because I do need the buttons to start an activity that displays device-specific information.
Ideally I would like to essentially create a template that I can just change the values of the text and the color of the indicator for
Below is my code:
// List of device names
val listView: ListView = findViewById(R.id.deviceList)
val arrayAdapter1: ArrayAdapter<*>
arrayAdapter1 = ArrayAdapter(
this#Homepage,
R.layout.device_button,
deviceNames
)
listView.setAdapter(arrayAdapter1)
listView.onItemClickListener =
AdapterView.OnItemClickListener { parent, view, position, id ->
val pos = position
println(pos)
val device = jsonArray.getJSONObject(pos)
val ID = device.get("id") as String
println(ID)
goToDeviceDetail(ID)
}
Below is the XML file for device_button. I tried to add formatting here and essentially create a template for a button that would allow me to change the text and the color of the indicator, but it got mad that it wasn't just a TextView.
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="40dp"
android:gravity="center_vertical"
android:textColor="#25383C"
/>
Below is the button that I would like for it to look like. I'm likely going to just make the background a solid color rather than the image that is in the below picture:
I would say the biggest problem is your using a simple API for a more complex problem. It is entirely possible do it with a ListView and ArrayAdapter. But I would highly recommend looking into RecyclerView/RecyclerView.Adapter
The way it works out is...
RecyclerView.Adapter binds your list of data ie Devices to the individual RecyclerView.ViewHolder
The ViewHolder would inflate your xml layout that contains the button. You then have access to all View contained in that layout easily.
You then can put listeners on the button.
The Adapter then can be setup to receive new data, when received it can rebind the data that has changed.
Say the user clicks one of the device buttons it does a task. When it gets back it will say hey Adapter I have a new List for you.(The list now contains the "fixed" device).
ViewModel(contains observable data)->Fragment/Activity(Observers the data)->Adapter(Receives the data)->ViewHolder(Displays the data)->Activity("Fixes the data")->ViewModel->...loops
Here is a very good example.
https://medium.com/#atifmukhtar/recycler-view-with-mvvm-livedata-a1fd062d2280
If you really want to keep using the ListView and ArrayAdapter you are receiving the clicked view here.
OnItemClickListener {
/*Parent of the view*/ parent,
/*The view clicked*/ view,
/*position of data*/position,
/*id of the view clicked*/ id
->{
view.findById(R.id.text_view);
//onClick
}
}
With that you know what has been clicked so you know what has to be changed later when you get back from your other Activity.
Related
I'm a Xamarin Android beginner. In an app that I'm writing, I created an Activity with a RadioGroup, and a button below it.
All was fine, until my radio buttons contained so much text that the radio group ran off the phone's screen, and the button was hidden.
So, I searched on the internet, and discovered that I could make the RadioGroup scrollable, by making it a ListView, and setting the ListView to be above the button.
Furthermore, I discovered that Xamarin Android offers the BuiltInView SimpleListItemSingleChoice which is a ready-made radio group as a ListView.
So, I implemented this, and all was fine, except that the text fields in each Item of the BuiltInView get cut short (i.e my radio button options to the user).
I want to apply the property
android:layout_height="wrap_content"
so that my long text labels for the radio buttons won't get cut short.
My question is, how do I apply this to each item of the BuiltInView?
I've tried to define my own custom view, but have run into problems trying to make it checkable, so I wondered if there is a simpler way to solve the problem by using the already provided BuiltInView.
In MyListAdapter GetView, I have
view = (context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItemSingleChoice, parent, false));
and in my Activity, I have
myListAdapter = new Adapters.MyListAdapter(this, myStrings, false);
myListView.Adapter = myListAdapter;
As the BuiltInView does not offer an xml file (or I don't know where to access it in Xamarin), I added the following code to the custom Adapter's GetView method:
var textLabel = view.FindViewById<TextView>(Android.Resource.Id.Text1);
//I added these 2 lines to set the WrapContent property on each element of the BuiltInView
AbsListView.LayoutParams layoutParams = new AbsListView.LayoutParams(AbsListView.LayoutParams.MatchParent,
AbsListView.LayoutParams.WrapContent);
textLabel.LayoutParameters = layoutParams;
I'm working on a Fragment that has a custom expandable ListView. When the ListView is selected, elements are added to two LinearLayouts within the selected list item and these layouts are made visible. Each of these new elements are selectable and have the following properties:
android:clickable="true"
android:background="?android:attr/selectableItemBackground"
I noticed that the handling of this background selector state is different on my two devices. I've attached two sets of screenshots for these devices to compare the handling of the same code.
Android 4.3.1 | CyanogenMod 10.2.1
Expanded, Sub-Element Clicked, List Item Clicked
Android 4.0.4 | 2.6.38.8-aokp-bravo-ics
Expanded, Sub-Element Clicked, List Item Clicked
As you can see on the 4.0.4 device when the whole list item is selected all the sub-elements get the focus highlight as well which is undesirable. How do I get around this?
I got tired of dealing with the inconsistencies (or maybe I never properly learnt) and did the following, which may or may not be correct or suit your scenario (treat the code below more like pseudo code than Java).
class SomeAdapter extends BaseAdapter {
final int colorItemDefault;
final int colorItemSelected;
final int colorSubItemDefault;
final int colorSubItemSelected;
public SomeAdapter (final Context c) {
final Resources res = c.getResources();
colorItemDefault = res.getColor (R.color.item_default);
colorItemSelected = res.getColor (R.color.item_selected);
colorSubItemDefault = res.getColor (R.color.sub_item_default);
colorSubItemSelected = res.getColor (R.color.sub_item_selected);
}
public View getView (final int position, final View convertView, final ViewGroup parent...) {
final View view = makeNewViewOrRecycleExisting (...);
final Item item = getItem (position);
// bind content, etc...
view.setBackgroundColor (isSelected (item) ? colorItemSelected : colorItemDefault);
// similar logic for the sub items
}
}
The color that you are seeing is because of the list view's listSelector property. The behavior of which effect will be rendered on list items depends upon the Android version and the theme that you have used for the application. To get around the problem either you set the listSelector to transparent or provide your own selector. You can set the listSelector in you xml or programmatically using either of them. Sets transparent color
android:listSelector="#00000000"
yourListView.setSelector(new ColorDrawable(0x0));
I have a messaging application. I can get messages and list from mysql database via json. When i get messages (for example last 10 messages and newer is at the bottom) first record is shown at the top, so user have to scroll down to see last message. I want to focus to last message and when user scrolls to top, I want to put there a Load Previous Messages button. I found Load More buttoni but its at the bottom of page. How can I do that?
My codes are these:
// Hashmap for ListView
categoryList = new ArrayList<HashMap<String, String>>();
// get listview
ListView lv = getListView();
Button btnLoadMore = new Button(this);
btnLoadMore.setText("Load older messages");
FrameLayout footerLayout = (FrameLayout) getLayoutInflater().inflate(R.layout.listfooter,null);
lv.addFooterView(btnLoadMore);
As I said in comments, simply change addFooterView() to addHeaderView() method which give you the Load More at the top of the list. This method use three parameters (at least one: View from reference) which are:
View v: the Load More view to add at the top
Object data: data associated to the view
boolean isSelectable: value to make the view selectable or not
Using these three params instead of only the view may allow you to prevent the color state on it by using android:listSelector attribute. Indeed, sometimes you want to prevent a background state on a header/footer view. That being says, the method might be:
lv.addHeaderView(headerLayout, null, false); // this isn't clickable now
Note: now, you can call the view variable headerLayout instead of footerLayout ;)
As I understand your requirements, HeaderView should have the Load More Button into it, to avoid to create it dynamically, as follows:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Load More"
android:onClick="loadMoreDatas" />
</LinearLayout>
Now, you have the right Button at the top of your list and you can add a method to handle the click event into the Activity (refer to android:onClick attribute) as:
public void loadMoreDatas(View v) {
// load more messages
}
Finally, to focus to a specific item, in your case the last item in the list (at the bottom), you should use setSelection(int position) which go to the index selected in its parameter. Then, after setting the Adapter, call this on the ListView as:
// set the adapter
setListAdapter(adapter);
// go to selection (last item)
lv.setSelection(adapter.getCount() - 1);
The getCount() method use (normally) your ArrayList size. Then, you have to prevent an IndexOutBoundsException because your array begins with position 0 and not 1. So, the last position is "All Items less First Position (0)".
However, the perfect method to begin at the bottom of the list is setStackFromBottom():
When stack from bottom is set to true, the list fills its content starting from the bottom of the view.
Then, it might be better to have:
// start from bottom
lv.setStackFromBottom(true);
This should do the trick and I hope this will be usefull.
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
I have set up a listview with one edit text widget. The listview is populated with a string file and I wanted to make changes on each item by clicking on the item. code builds and the listview shows as planned. When the item is clicked it gets focus but then looses focus after the keyboard pops up without any entries.
els_edit_tiles.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<EditText
android:id="#+id/listText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" >
</EditText>
This is the onclicklistener, I assume the changes will need to be here and did not post the adapter code.
private class ListClickhandler implements OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> Adapter, View view, int position, long arg3) {
TextView listText = (TextView) view.findViewById(R.id.listText);
String text = listText.getText().toString();
// Toast.makeText(context, text + " " + position, Toast.LENGTH_LONG).show();
}
}
I assume you mean the item loses its highlight, rather than focus. Focus goes wherever you tap and is there whether the highlight shows or not. So, I'll explain some options for the disappearing highlight.
For better or worse, they've designed it this way. You have a few choices. One is to subclass ListView and try to figure out how to add a sticky highlight. (I tried that and got it to work, but abandoned it for another reason - I wanted to put the list in a ScrollView, which doesn't work with a ListView).
Another choice: use a spinner (aka a drop down list). This doesn't exactly do what you're asking but it does show you which item was selected -- it is the one that shows when the spinner collapses.
Yet a third choice (I implemented this) - Use a LinearLayout and add each item as a child of the layout. You have to implement your own selection and highlighting, but that takes relatively little code (I can help if you need). This effectively gives you a list that shows all items - it doesn't scroll. You can include it in a ScrollView along with other elements to scroll the whole collection together.