Android ListView/Recyclerview dynamic content - android

Hello I am iOS developer just started with android, I know basic concepts of android like RecyclerView, ListView.
I want to make a feed page in which each row can contain one photo and multiple comments, no of comments are dynamically changing depending on data.
How to achieve the same using RecyclerView/ListView?
I can achieve the same in iOS like this : http://t.co/z1IRHTTjED

If you already know concepts of ListView and RecyclerView you should know that we use Adapters to provide views for List.
You can create a custom Adapter which will create a view, where, depends on data you have, you will display comments or not.
Edit.
For example you have a layout like this
<LinearLayout>
<ImageView />
<TextView android:id="#+id/comments" />
</LinearLayout>
in your adapter you should call
TextView comments = (TextView) findViewById(R.id.comments);
if(haveComments) {
comments.setVisibility(View.VISIBLE);
//display comments
} else {
comments.setVisibility(View.GONE);
}
If you need to have more complex layout for comments, for example with images, and date field, instead of TextView declare LinearLayout with vertical orientation. You can fill it with items from code.
LinearLayout commentsLayout = (LinearLayout) findViewById(R.id.commentsLayout);
if(haveComments) {
comments.setVisibility(View.VISIBLE);
//display comments
commentsLayout.addView(inflateCommentView());
} else {
comments.setVisibility(View.GONE);
}
private View inflateCommentView() {
View myComment = LayoutInflater.from(context).inflate(R.layout.my_complex_comment, null);
//set listeners, fill with data
return myComment;
}

Related

Creating large amount of Views in Code

I'm trying to create a custom View that contains a list of CheckBoxes based on my database. This means I have to create the Views at run-time, and can't do it in XML. However, the method I'm using for this is very slow. Is there a faster method to create large amount of Views in code?
For example, with the 18 types in my database, it can take over 1 second to create all the CheckBoxes.
class FilterView : LinearLayout {
private fun init(types : List<Type>){
... setup
// Creating the CheckBoxes, this takes all the time.
checkboxes = Array(types.size, {
AppCompatCheckBox(context).apply {
text = types[it].type
CompoundButtonCompat.setButtonTintList(this, ColorStateList(states, intArrayOf(colours[it], colours[it])))
}
})
... add to view
}
What your looking for is a Recyclerview. It can all be explained here. The downvote was likely because this is assumed to be common knowledge or easily googled on your own. I was new once too. Here you go.

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.

Android: dynamically cycle through layout items

Not sure if the head line describes its well, what I want is that:
I have let's say 9 TextViews in my layout, named tv1, tv2, ..., tv9.
Of course I can access each of them with
TextView tv11 = (TextView) findViewById(R.id.tv1)
Lot's of typing, so I rather would have a loop and loop through these items, but how can include the findViewbyId into a loop that I can change the value accordingly?
Is there any reason why you can't iterate over the children of the containing ViewGroup? So you get the number of children with getChildCount and then you can access each individual child with getChildAt.
You may have to test whether a particularly child is an instance of TextView if you have other views in the layout, but the basic concept is fairly straightforward.
You could make an array of the IDs you want to loop through.
IE:
public static final int TEXTVIEW_IDS = { R.id.tv1, R.id.tv2, R.id.tv3, etc.. };
In your view code:
for (int id : TEXTVIEW_IDS) {
((Textview) findViewById(id)).CallYourMethod();
}
If you cannot do what #James Holderness suggested, this may be a suitable alternative.

Populating data on gridview

In my android app, i have a particular scenario, for one of the screens.
I require 2 button,one on each side of the corner(left and right).
Below this i want to populate data in a control.
If left button is clicked, the control should be a gridview.
If right button is clicked , the control should be a listview.
And accordingly the data should be populated.
How should i approach this scenario.
Should i create controls dynamically, or use xml instead
Rgds
Create the view with two different layouts.
Assume that you have 2 xml layouts named gridLayout.xml and listLayout.xml
and that somehow mode is determined earlier in your code and set to one of two constants GRIDVIEW or LISTVIEW. Than you can use a code fragment like:
private Context m_Context = activity.getBaseContext();
private ViewHolder m_Inflater = LayoutInflater.from(m_Context);
...
if (mode == GRIDTYPE)
viewDisplay = m_Inflater.inflate(R.layout.gridLayout, null);
} else {
viewDisplay = m_Inflater.inflate(R.layout.listLayout, null);

Displaying a list with different types of information in Android

I want to create a page with X questions (the questions are stored in a database and I read them), headline and buttons at the end.
When the user clicks on one question than the question should transform into a dialog where the user can modify the question, however the other questions above and beneath it should still display the same way.
The way ListActivity is used in the sample notepad application in the android documentation it seems like the class can only display multiple items of the same type.
Is there a straightforward way to go about this problem?
I should tell you that I don't like your solution as an user.
I would prefer to chose from a list and having an edit activity after a click.
That's the default approach I've seen in every android app and it will be also easier for you.
If you still want to do what you explained I would try do this:
Create a ListView
Create a class QuestionOrDialog
Create an Adapter that extends from ArrayAdapter
Override getView doing something like:
QuestionOrDialog aQuestionOrDialog = getItem(position);
if ( aQuestionOrDialog.showDialog() ) {
return mInflater.inflate(R.layout.dialog, parent, false);
} else {
view = mInflater.inflate(R.layout.question, parent, false);
TextView question = (TextView) view.findViewById(R.id.question);
question.setText(aQuestionOrDialog.getQuestion());
}
On the OnClick you will have to do a getItem() and set that it was clicked.
Tell the listView that it's item have changed.
Hope it works.

Categories

Resources