ArrayAdapter for Webview inside Gridview - android

Following on from an earlier question I'm trying to get multiple (widgets or in this case WebViews) inside a GridView.
So I wasn't really sure how to go about it whether to make my own adapter (seemed scary at the time) or create an ArrayAdapter<WebView>.
I wasn't really sure if ArrayAdapter could accept it like this or if it only supported primitive types.
GridView contentGrid;
LinearLayout contentLayout;
WebWidget[] webWidgets;
WebWidget web1;
WebWidget web2;
WebWidget web3;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
web1 = new WebWidget(this, "http://www.google.ie");
web2 = new WebWidget(this, "http://www.facebook.com");
web3 = new WebWidget(this, "http://www.youtube.ie");
webWidgets = new WebWidget[]{web1,web2,web3};
contentGrid = (GridView) findViewById(R.id.contentGrid);
//Heres my attempt at an adapter for webview
ArrayAdapter<WebView> adapter = new ArrayAdapter<WebView>(this,
android.R.layout.simple_list_item_1, webWidgets);
contentGrid.setAdapter(adapter);
Unfortunately what comes out is the string version of the WebView.
So question is can I do it this way or am I better of making my own CustomAdapter?
NOTE: Could someone maybe point some information as to what the second constructor variable is? I.E android.R.layout.simple_list_item_1

No matter how you implement your Adapter, you cannot reliably put scrollable widgets in other scrollable widgets, at least where they scroll in the same direction. Since both WebView and GridView scroll vertically, you will get unreliable results trying to combine them this way.
With that, on to some of your statements and questions:
I wasn't really sure if ArrayAdapter could accept it like this or if it only supported primitive types.
An ArrayAdapter can adapt a Java array or an ArrayList of whatever data type you like.
Unfortunately what comes out is the string version of the webview...NOTE: Could someone maybe point some information as to what the second constructor variable is? I.E android.R.layout.simple_list_item_1
The second constructor variable is what you want the cells in your GridView to look like. In your case, you are specifying a built-in layout resource that is a TextView. Hence, you are telling Android you want all your grid cells to be TextView widgets. Android will call toString() on the objects in your array, pour that result into the TextView, and the TextViews will go in your grid cells.
If you want your ArrayAdapter to be returning things other than a TextView, you will need to override getView() and handle more of that yourself, possibly using a layout file of your own creation.
So question is can I do it this way or am i better of making my own CustomAdapter?
As noted at the outset of my answer, what you want simply will not work reliably.
Pretending for the moment that having WebViews in a GridView would work, the simplest solution would be for you to override getView() in your own subclass of ArrayAdapter, as I mentioned previously. Here is a free excerpt from one of my books that goes over this process.

Related

How do I initialize elements of a GridView on creation?

My android is very rusty, so this is the best way I can explain this:
A card contains an image, a value, and a URL
I have an array of values, a parallel array of images, and of URLs (values[i] <-> images[i] <-> URLs[i])
Have a GridView that I want to use to display many of these cards
The problem:
I have a class that extends BaseAdapter to create a custom view to display the three elements of the card
Using the getView method of said adapter, I use the "i" expected by getView as a mental index of which card we are talking about.
Unfortunately I realized that i=0 means the currently visible first card, I thought it meant the overall first card. This makes it useless as a system to keep track of the overall position of cards.
So, the visible elements are populated correctly in the view. But, if I scroll down and then back up, some internal elements have been jumbled up. So clicking a card might now lead to the URL of a card that was initialized after it.
What I need help with:
A better way to index or populate each card's content that will be permanent.
I am wildly confident I am doing this in a horrendous way. I'm imagining there must be some way to say that:
When GridView is created -> populate each card's details and fill in GridView.
Current Main Activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_card_list);
gv = (GridView) findViewById(R.id.cardGridView);
gv.setAdapter(new CardView(this, cardURLs, cardNames, cardPrices, cardImages));
}
Current CardView Activity:
public CardView(CardListActivity mainActivity, String[] cardURLs, String[] cardNames, Double[] cardPrices, int[] cardImages){
//...
inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public class Holder{
TextView priceTV;
ImageView cardIV;
String cardName;
}
#Override
public View getView(final int i, View convertView, ViewGroup parent) {
//...
View rowView;
rowView = inflater.inflate(R.layout.card_item_view, null);
//HERE IS WHERE I SET THE PRICE AND IMAGE USING i
holder.priceTV.setText("$" + prices[i].toString());
holder.cardIV.setImageResource(images[i]);
//...
return rowView;
}
Turns out the problem was something else.
The actual problem ended up being caused by these Dialogs I would create to verify if the user wanted to open the website.
I was creating them inside getView, all in the same variable, which meant that the last elelemnt to get initialized would be the one used in the dialog.
I fixed this by moving the dialog creation into the onClick for the view.
Firstly, You should wrap your contents into objects so that each CardContent object contains a url, an image and a value, Then pass those into your adapter. That will be much easier on you, you only need to maintain 1 List of CardContent rather than 3 individual lists and hoping the order doesn't get messed up.
Secondly, This sounds like a case for a Recyclerview. You can use a GridLayoutManager with a Recyclerview instead of a GridView so that your views get recycled and you have less overhead. Luckily the code is largely the same.
See https://developer.android.com/training/material/lists-cards.html for pretty much what you want.

ListView Example with Simple Java Objects for Items

I'm new to Android programming. I can get simple ListViews to work in which I use an ArrayList of strings. I want to take a step upward in complexity and have my ListView be composed of simple Java objects like this:
class myItem {
public String name;
public Integer price;
public Integer weight;
}
The ListView only needs to display the name in the above object. It doesn't have to have multiple icons, or multiple clickable actions for each item.
But I don't know where to start. All of the examples I see on the WWW are much more complicated and require me to learn things that have nothing to do with this (like a database). Or each ListView items is displayed with multiple views like text and images and icons etc. and each is clickable for a different action. I don't need any of that, and I'm getting bogged down reading about unneeded features in order to get those examples to work.
Does anyone have an example of a simple ListView that contains simple Java objects (like the one above)?
But I don't know where to start.
Implement a public String toString() method on myItem. Then create an ArrayList<myItem> and use that instead of ArrayList<String>, populate that list with suitable myItem instances, and put the list into an ArrayAdapter<myItem> instead of an ArrayAdapter<String>. No other changes should be required -- whatever layout you are using for an ArrayAdapter<String> will work with your ArrayAdapter<myItem>.
In case you are new to Java, toString() is the standard Java method for returning a String representation of an object. The default behavior of ArrayAdapter is to call toString() on the object for the given list position and use that to fill in the row.

Using text files and XML defined strings to populate lists

I am writing an application which contains a few simple views; first is just two buttons. each button leads to a map, and from this map is a button which opens a list of buildings on the site. From here the user will be able to select a building and view detailed information on it (much like a contacts list actually).
So far, I am able to populate the listview by creating the string array to populate it it directly within the activity, like so:
public class BuildingsActivity extends ListActivity {
static final String[] buildings=new String[]{
"Building 1",
"Building 2",
"Building 3",
"Building 4",
"Building 5"
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_buildings);
// Show the Up button in the action bar.
getActionBar().setDisplayHomeAsUpEnabled(true);
setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,buildings));
}
This works all well and good for a 5 item list, but in it's final form, the list may contain up to a hundred buildings, and I have 2 concerns:
1) A one-hundred item long string array is going to look really gross defined in code like this
2) I am worried about how long it will take the application to open the activity if it has to generate such a large list of string values beforehand
To avoid this, I had the idea to define this string array in the strings.xml file and assign the strings to the list layout in the corresponding layout XML for the list activity. However, this so far doesn't seem to work; no errors but the android:entries command does not see to affect the layout at all. This is the XML. If anybody has knowledge of populating a list this way, I would appreciate your answers.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".BuildingsActivity" >
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="#array/buildings">
</ListView>
</RelativeLayout>
My other alternative is to retrieve it from a text file, which I will have to do for building details (as the volume of text is too large to bother saving as strings) but wanted to avoid for the list. Admittedly, I have not heavily researched this route (both because I had not really wanted to use it yet and based on what I have seen on other forums it looks difficult, but if there is a lot of support for this method then I will certainly appreciate any advice in using it.
Forgive me if any of this has already been covered in other threads. I DID search for similar topics, but nobody seemed to want to populate a list this way and a lot of the language from their questions went over my head (I am very new...this is my first real application, besides having worked through some of the tutorials on the developer website.
Java's ArrayList implements the Serializable interface, which allows you to save and load an array to and from a pure binary format using the functions writeObject and readObject. This page should be enough to get you started.
If you want to populate the listView with from a resource file you just have to use this in your code:
String[] values = getResources().getStringArray(R.array.<input_file>);
Once you have the values loaded you just have to assign it to the ArrayAdapter like this:
adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, values);
setListAdapter(adapter);
The second parameter is a predefined layout of android SDKs, you could use your own layout.
If your String[]'s ceiling is 100, I don't see it as a problem to just generate the array and pass it to the adapter. As for your concern about the code looking gross, have you considered storing this information in a database and then requesting it? For instance, you could have a Building Entity, with all of its information and persist it to MySQL using OrmLite. http://ormlite.com/javadoc/ormlite-core/doc-files/ormlite_1.html#SEC1 You could then write a getter than returns an array representation to avoid the ugly code.

Setting tags to each item in a ListView in Android?

I have a ListView where I want each item to have an ID number attached to it (not the same as the position number). I was hoping this could be done by setting a tag to each View item in the ListView using setTag() when these Views are being created.
Right now I'm creating the ListView like this:
final ListView listview = (ListView) findViewById(R.id.listView1);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, names);
listview.setAdapter(adapter);
The names variable in the ArrayAdapter parameters above is an ArrayList, and each string value in this list also has a unique ID that I want to link to this string somehow.
Is there any way I can get access to and modify each of the Views with a tag? One idea was to create my own extended class of ArrayAdapter and override the getView() method, but I don't really understand how it works and how I would go about doing this.
Or is there a better way to link IDs with each string like this than adding tags like I'm trying to do?
Create a ViewBinder and set the tags as the ListView is being populated with whatever you need. You can check all properties of the view to determine what tag goes where, so this should be what you're looking for.
myAdapter.setViewBinder(new MyViewBinder());
public class MyViewBinder implements ViewBinder {
#Override
public boolean setViewValue(View view, Object data, String text){
//Since it iterates through all the views of the item, change accordingly
if(view instanceof TextView){
((TextView)view).setTag("whatever you want");
}
}
}
I just used this exact same answer on another question (albeit slightly different) yesterday.
about getView , it works by using a method of recycling views. i will try to explain it in a simple way.
suppose you have tons of items that can be viewed . you don't want to really create tons of views too , since that would take a lot of memory . google thought of it and provide you the means to update only the views that need to be shown at any specific time.
so , if there is an empty space on the listview , it will be filled with a new view . if the user scrolls , the view that becomes hidden is recycled and given back to you on the getView , to be updated with the data of the one that is shown instead .
for example , if you scroll down , the upper view becomes hidden for the end user , but in fact it becomes the exact same view that is on the bottom .
in order to understand how to make the listview have the best performance and see in practice how and why it works as i've talked about , watch this video:
http://www.youtube.com/watch?v=wDBM6wVEO70
as for tags , i think you want to do something else , since the data itself (usually some sort of collection, like an arrayList) already knows where to update , because you get the position via the getView . if you want a specific view to update , you might be able to do so by using a hashmap that keeps upadting , which its key is the position in the collection , and the value is the associated view . on each time you go to getView , you need to remove the entry that belong to the view (if exists) and assign the new position with the view that you got/created .
Thanks for the answers. thisMayhem's answer would probably have been easier in the end, but on my quest to learn more I ended up making my own adapter according to this tutorial. I pass down the names and the IDs into the adapter and set the names as the text of the TextViews and the IDs as the tags.
I would rather go with the solution discussed in this thread. It is always the easiest to have all related data in same place and in this case you just create a class to hold all the information you will need for every item.

I need help populating a listview from a remote source in android

I've searched far and wide for this answer and can't seem to find it.
I'm looking to populate a very simple 3 line listview, no more then 5-6 words per line at the most inside of my android app.
I'm currently using a base adapter and a string array to enable the actual text to show up on the screen.
I want to have the ability to update the information inside of my listview remotely using
some sort of means whether that's xml, SQLite, plain text, etc and then have that hosted file populate my listview.
Can anyone here help me to figure out how to do this? I'm still pretty new to android development so please go easy on me. Hopefully this question wont be too hard answer and also not too difficult to enable for a newbie like myself.
If the most you're going to ever have in there is just 3 lines of text, I think a SQLite DB may be a bit much for your situation. I'd look into using a Typed Array.
Here's a link to the Android Dev Guide on this subject:
http://developer.android.com/guide/topics/resources/more-resources.html#TypedArray
Here's a code sample:
public class YourListActivity extends ListActivity {
String[] mTestArray;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create an ArrayAdapter to contain your items
ArrayAdapter<String> adapter;
mTestArray = getResources().getStringArray(R.array.yourArray);
// Assign your array to an adapter with your layout file
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mTestArray);
// Assign the adapter to this ListActivity
setListAdapter(adapter);
}
}
EDIT
Just realized that your data will be on a remote server, so this approach may not work for you, but it can still give you an idea of how to take your data once received from your remote server and place it into a ListView.

Categories

Resources