I have a ListView and each row contains a different User object.
A User has these different fields:
List of things I like
List of things I hate
List of games I play
Description of myself
Now, when I populate the ListView, I want to show different things that each user has filled out. So for example, one row might show 'things I like' filled out, while another might show the 'description of myself'.
I don't want to adjacent rows to be showing the same type of row. All this code will be inserted into my BaseAdapter's getView methood.
What would be the best logic in terms of pseudocode to achieve this?
Thanks in advance!!
Updated: Solution
// Creates arraylist of elements that are complete in profile
List<String> profileElements = new ArrayList<String>();
if (user.getGameOwned() != null && user.getGameOwned().size() > 2) {
profileElements.add(KEY_GAMES_PLAYED);
}
if (user.getAboutMe() != null && !user.getAboutMe().isEmpty()) {
profileElements.add(KEY_ABOUT_ME);
}
if (user.getIAm() != null && user.getIAm().length > 2) {
profileElements.add(KEY_I_AM);
}
if (profileElements.size() > 0) {
String randomElement = profileElements.get(new Random().nextInt(profileElements.size() - 1));
if (randomElement.equals(KEY_GAMES_PLAYED)) {
// do whatever here
}
else if (randomElement.equals(KEY_ABOUT_ME)) {
// do whatever
}
}
You could try this approach, in your BaseAdapter put a verification if what list do you want to show.
For example:
int ctr = 1; // your counter - try to declare it on the global level
if(ctr<4){//your 4 types of list -
display(ctr); //print the current ctr
ctr++;
}else{
display(ctr);
ctr = 1; //make the value to 1 for the next batch of loop
}
code:
display(int index){
switch (index){
case 1:
//List of things I like
break;
case 2:
//List of things I hate
break;
case 3:
//List of games I play
break;
case 4:
//Description of myself
break;
default:
break;
}
}
You could also do random.nextInt(4) but it might have the same result each row.
I think what you're trying to do could be achieved using an ArrayAdapter and a custom row layout. It is well explained in this article. I'd recommend reading the whole thing but section 6 explains what you want to do.
Related
Smiley Rating bar
Hello,I just getting started with android ,and I am trying to use smiley rating bar,i add it to my project,
my problems is :
1-Get current selection (the choice of the user) i read the instructions on the git,but i didn't understand how can i get the user choice.
2-send that choice or the selection of the user to an email address without opening the email app ( directly send ).
this the git https://github.com/sujithkanna/SmileyRating.
Bind the view from xml in your java class by smileRatingBar = findViewById(R.id.smile_rating_bar_id);
then you need to add listener for it:
smileRatingBar.setOnSmileySelectionListener(new SmileRating.OnSmileySelectionListener() {
#Override
public void onSmileySelected(#BaseRating.Smiley int smiley, boolean reselected) {
// reselected is false when user selects different smiley that previously selected one
// true when the same smiley is selected.
// Except if it first time, then the value will be false.
switch (smiley) {
case SmileRating.BAD:
Log.i(TAG, "Bad");
break;
case SmileRating.GOOD:
Log.i(TAG, "Good");
break;
case SmileRating.GREAT:
Log.i(TAG, "Great");
break;
case SmileRating.OKAY:
Log.i(TAG, "Okay");
break;
case SmileRating.TERRIBLE:
Log.i(TAG, "Terrible");
break;
}
}
});
Your first query i.e. how to know the current selection (the choice of the user) can be known by the following way :
SmileRating smileRating = findViewById(R.id.feedback_rating);
int level = smileRating.getRating();
Where Level will return 0 if NONE selected else will return 1 to 5 ranging where 1 is Terrible while 5 is Great.
I'm developing chat application and i've already design dummy chat history.But i'm stuck at how to group messages according to it's date and when we scroll it down,date indicator stick at the top position just like whats app. can you just show me the way, how can i achieve that? I've attached some screenshot below to elaborate my question.
Put your header in your custom lisview adapter layout and check everytime your current message date and previous message date. If date is same then hide your header otherwise show your header. See below:
holder.tvDate.setText(chatMessage.getDate());
if (position > 0) {
if (chatMessages.get(position).getDate().equalsIgnoreCase(chatMessages.get(position - 1).getDate())) {
holder.header.setVisibility(View.GONE);
} else {
holder.header.setVisibility(View.VISIBLE);
}
} else {
holder.header.setVisibility(View.VISIBLE);
}
Simple. Just add a header view to your ListView
TextView textView = new TextView(context);
textView.setText("Hello. I'm a header view");
listView.addHeaderView(textView);
for more details- https://developer.android.com/reference/android/widget/ListView.html#addHeaderView(android.view.View)
Update:
By far the simplest way to do this is to embed the date header view in every item. Then, all you need to do in bindView is compare the previous row's date to this row's date, and hide the date if it's the same. Something like this:
String thisDate = cursor.getString(dateIndex);
String prevDate = null;
// get previous item's date, for comparison
if (cursor.getPosition() > 0 && cursor.moveToPrevious()) {
prevDate = cursor.getString(dateIndex);
cursor.moveToNext();
}
// enable section heading if it's the first one, or
// different from the previous one
if (prevDate == null || !prevDate.equals(thisDate)) {
dateSectionHeaderView.setVisibility(View.VISIBLE);
} else {
dateSectionHeaderView.setVisibility(View.GONE);
}
I'm creating a memory app (you know where you have to select 2 images and match them). I'm looking for a way to check when there are no images left so I can show a message.
I have this code to check if the images match. I'm working with 2 arrays, 1 holds the imageviews and their position in the grid (playfield) and one holds the reference for which image is on that imageview (cards).
private void checkCards() {
if (cards[value1] == cards[value2]) {
playfield[value1].setBackgroundResource(R.drawable.border_red);
playfield[value2].setBackgroundResource(R.drawable.border_red);
playfield[value1].setClickable(false);
playfield[value2].setClickable(false);
score++;
} else {
playfield[value1].setImageResource(R.drawable.back);
playfield[value2].setImageResource(R.drawable.back);
}
value1 = -1;
value2 = -1;
}
I need to check on one of these conditions:
There are no more imageviews without a red border
There are no more imageviews that are clickable
There are no more imageviews with the R.drawable.back imageresource
However I'm not sure on how to do this? Do any of you have an idea or even a better method?
Thanks in advance!
I would keep a counter of each one, I can think on more complicated solutions, but a pretty straightforward one will be to have a counter and increase that counter when you're assigning the clickables, the borders, etc... e.g:
private void checkCards() {
if (cards[value1] == cards[value2]) {
playfield[value1].setBackgroundResource(R.drawable.border_red);
playfield[value2].setBackgroundResource(R.drawable.border_red);
playfield[value1].setClickable(false);
playfield[value2].setClickable(false);
mCounterClickables--; // one less clickable
mRedDrawables++; // one more Red Drawable
mBlackDrawables--;
score++;
} else {
playfield[value1].setImageResource(R.drawable.back);
playfield[value2].setImageResource(R.drawable.back);
mBlackDrawables++; //
}
value1 = -1;
value2 = -1;
}
Then to validate that you're done:
public boolean imDone() {
return mBlackDrawables == 0 && mCounterClickables== 0
&& mRedDrawables == playfield.length;
}
Does it makes sense?
In this way you don't have to iterate over and over again, you will always have track of what the user has done.
Btw. The initial state of your variables should be something like this:
int mBlackDrawables = 0, mCounterClickables = playfield.length, mRedDrawables = 0;
I am trying to dynmically move several rows around at once within a specific view based on user input.
The use-case is that the user picks an option and based on the option, certain rows are show/hidden and the rows need to be rearranged to make sense to the user.
The TableLayout is instantiated in XML, but the TableRow and it's layout(s) are instantiated in code. I have tried several different methods, with varying levels of success.
Code which works for hiding/disabling properly:
private void updateTimeRow(TargetType goalTarget)
{
TableRow timeRow = (TableRow)this.findViewById(timeId + 100);
EditText timeText = (EditText)this.findViewById(timeId);
if (goalTarget == TargetType.daysRowedWeek
|| goalTarget == TargetType.metersDay
|| goalTarget == TargetType.metersSeason
|| goalTarget == TargetType.metersWeek)
{
timeRow.setVisibility(View.GONE);
timeRow.setEnabled(false);
timeText.setEnabled(false);
}
else if (goalTarget == TargetType.splitForDistance
|| goalTarget == TargetType.unknown)
{
setTimeText(currentTarget.recalcTime().toString());
timeRow.setVisibility(View.VISIBLE);
timeRow.setEnabled(false);
timeText.setEnabled(false);
}
else
{
timeRow.setVisibility(View.VISIBLE);
timeRow.setEnabled(true);
timeText.setEnabled(true);
}
}
Based on questions answered here, I tried removing/re-adding rows, with this piece of code:
int rowNum = -1;
tableLayout.removeView(timeRow);
switch (goalTarget)
{
case unknown:
case timeForDistance:
rowNum = 2;
break;
case splitForDistance:
rowNum = 4;
break;
case splitForTime:
rowNum = 3;
break;
}
tableLayout.addView(timeRow, rowNum);
Two things break here:
The disable code fails (whether this code is run before of after the enable/disable code above
The rows in my layout get all screwed up.
So, how do I move the rows around dynamically, while properly hiding/showing/enabling/disabling the different rows?
After a lot of frustrating trial and error, I finally figured out the only way to do this with solid results:
I had to adjust the way my UI was updating, to a 3-step process:
- Update the values for the Inputs (enforces formatting, re-calcs, etc)
- Re-layout the rows
- Enable/disable the different inputs based on the selections
The nuts and bolts is that anytime the goalTarget changes I have to remove all of the TableRows from the TableLayout and add
them back in the correct order, with the appropriate row numbers as part of the addView() call.
This is definitely not the prettiest way I could see it being done, but apparently the TableLayout doesn't like you just trying
to move things around one at a time.
I have 20 cards of which there are 10 pair of images. The player is meant to find a match of each card/image.
The problem is that if a player taps or clicks each card twice then that card gets decremented from the remaining ones . I need to disable the click listener of the ImageView. How can do that?
ivOne = (ImageView)findViewById(R.id.ivOne);
ivOne.setId(a[0]);
//final ImageView ivOne = (ImageView)findViewById(R.id.ivOne);
//ivOne.setEnabled(false);
ivOne.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
ivOne.setBackgroundResource(images[a[0]]);
Log.e("r[0]:", Integer.toString(a[0]));
if (firstTap)
{
firstId = v.getId();
firstTap = false;
}
else
{
//ivOne.setEnabled(false);
int secondId = v.getId();
Log.e("secondId", Integer.toString(secondId));
if ((secondId == firstId) && (score != 0))
{
//ivOne.setEnabled(false);
if (ivOneScored == false)
{
score--;
ivOneScored = true;
}
}
firstTap = true;
}
tvScore.setText("Remaining:" + Integer.toString(score));
}
});
I have a memory matching game on the market that works very similar. What I did was make a class that represents the card (with image and id properties) and assign an id (0-9) to the cards and the image as I loaded them into a temporary arraylist of just the 10 image objects.
public class GameTile {
public int id;
public Drawable image;
}
Then I iterated over the list twice and added the cards to the main arraylist that I use for my adapter... after which I used Collections.shuffle to shuffle the cards... Now... on to the selection. AS you know, in a memory game, you only want 2 cards flipped at any time. I am using a gridview to hold my cards... so what I did was use the OnItemClickListener from the gridview and not the imageview. Secondly, when a card is clicked, I add the position to another arraylist called "selected" that never contains more than 2 items... the position of the items we are attempting to match... In the OnItemClickListener, when the event is fired, I check to see if the item already exists in "selected" and return if it does... in effect ignoring the click.
if (selected.contains(position)) {
return;
}
When "selected" contains 2 items, I ignore all clicks until the handler finishes checking for a match.
if (selected.size() > 1) {
return;
}
So when a user has selected 2 items, I set a handler to call a runnable that checks for a match. If a match is made (by comparing the id fields I set when I first loaded the images), I add the two positions to another arraylist that contains only matched items and that handler also clears "selected" and, if there were matches, I change the images to blanks. When all 20 cards have been matched I fire a win which does all of the win stuff and resets the gameboard.
You have to make sure that those cards have the same symbol, but are not the same card.
So your line
if ((secondId == firstId) && (score != 0))
must rather look like something in the lines of
if ((firstCard != secondCard) && (secondId == firstId) && (score != 0))
where firstCard and secondCard identify the card on the table (not the symbol on the card)
If I understand you right, you just need to say view.setOnClickListener(null) if those two match? If you want to disable both of them, you just store a map to link an ID to a View, and then clear the click listener for both "view" and whichever view belongs to the second ID.