I want to get familiar with Android and started taking some Udacity courses. Currently, we have to make an ImageButton play some audio on click for language-learning purposes.
I thought it would be nice if the button toggled as well, for example, in a paused state, it should display a "play" icon and in a playing state, a "pause" icon. This is very simple to achieve using an OnClickListener and it also works properly, up to 1 small detail: the user has to click the button twice.
After some searching, I found out that the first click is used to focus the view in that position and the second view is when the fired OnClickEvent is actually handled. I tried to change the focusable and focusableInTouchModeattributes to all possible combinations in all possible places, but it didn't work.
Here is my main Activity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView numbersView = findViewById(R.id.numbers);
numbersView.setOnClickListener(v -> {
Intent numbersIntent = new Intent(MainActivity.this, NumbersActivity.class);
startActivity(numbersIntent);
});
TextView familyView = findViewById(R.id.family);
familyView.setOnClickListener(v -> {
Intent familyIntent = new Intent(MainActivity.this, FamilyActivity.class);
startActivity(familyIntent);
});
TextView colorView = findViewById(R.id.colors);
colorView.setOnClickListener(v -> {
Intent colorsIntent = new Intent(MainActivity.this, ColorActivity.class);
startActivity(colorsIntent);
});
TextView phrasesView = findViewById(R.id.phrases);
phrasesView.setOnClickListener(v -> {
Intent phrasesIntent = new Intent(MainActivity.this, PhrasesActivity.class);
startActivity(phrasesIntent);
});
}
}
Here is the corresponding xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical"
android:divider="?android:dividerHorizontal"
android:showDividers="middle"
android:background="#212121">
<TextView
android:id="#+id/numbers"
style="#style/CategoryStyle"
android:layout_height="wrap_content"
android:text="#string/numbers"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textColor="#b794f6"/>
<TextView
android:id="#+id/family"
style="#style/CategoryStyle"
android:layout_height="wrap_content"
android:text="#string/family"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textColor="#90CAF9"/>
<TextView
android:id="#+id/colors"
style="#style/CategoryStyle"
android:layout_height="wrap_content"
android:text="#string/colors"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textColor="#EEEEEE"/>
<TextView
android:id="#+id/phrases"
style="#style/CategoryStyle"
android:layout_height="wrap_content"
android:text="#string/phrases"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textColor="#FFE082"/>
Here is my NumbersActivity (the other activities are very much alike):
public class NumbersActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.word_list);
ListView view = findViewById(R.id.coolList);
List<Word> words = new ArrayList<>(Arrays.asList(
new Word("lutti", "one", R.drawable.number_one, R.raw.test_audio),
new Word("otiiko", "two", R.drawable.number_two, R.raw.test_audio),
new Word("tolookosu", "three", R.drawable.number_three, R.raw.test_audio),
new Word("oyyisa", "four", R.drawable.number_four, R.raw.test_audio),
new Word("massokka", "five", R.drawable.number_five, R.raw.test_audio),
new Word("temmokka", "six", R.drawable.number_six, R.raw.test_audio),
new Word("kenekaku", "seven", R.drawable.number_seven, R.raw.test_audio),
new Word("kawinta", "eight", R.drawable.number_eight, R.raw.test_audio),
new Word("wo'e", "nine", R.drawable.number_nine, R.raw.test_audio),
new Word("na'aacha", "ten", R.drawable.number_ten, R.raw.test_audio)));
WordAdapter itemsAdapter = new WordAdapter(this, words, getColor(R.color.numbers_category));
view.setAdapter(itemsAdapter);
}
}
//I know that doing it like this isn't that great, I just needed to get something up and running and worry about these changes later.
Here is the xml to that:
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="#+id/coolList"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:divider="#B0BEC5"
android:dividerHeight="2dp"
android:background="#212121"
android:focusable="false"
android:focusableInTouchMode="false"></ListView>
Here is the Word Class:
public class Word {
private String miwokTranslation;
private String defaultTranslation;
private int ressourceID = -1; //just init, in order to check for it later
private int audioID;
public Word(String miwokTranslation, String defaultTranslation, int ressourceID, int audioID) {
this.miwokTranslation = miwokTranslation;
this.defaultTranslation = defaultTranslation;
this.ressourceID = ressourceID;
this.audioID = audioID;
}
public Word(String miwokTranslation, String defaultTranslation, int audioID) {
this.miwokTranslation = miwokTranslation;
this.defaultTranslation = defaultTranslation;
this.audioID = audioID;
}
public String getMiwokTranslation() {
return miwokTranslation;
}
public String getDefaultTranslation() {
return defaultTranslation;
}
public int getResourceID() {
return ressourceID;
}
public int getAudioID() {
return audioID;
}
#Override
public String toString() {
return miwokTranslation + "\n" + defaultTranslation;
}
}
Here is the corresponding Adapter:
public class WordAdapter extends ArrayAdapter<Word> {
private final int color;
Context context;
public WordAdapter(#NonNull Context context, #NonNull List<Word> objects, int color) {
super(context, 0, objects);
this.color = color;
this.context = context;
}
#RequiresApi(api = Build.VERSION_CODES.O)
#SuppressLint("ClickableViewAccessibility")
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent, false);
}
Word item = getItem(position);
ImageView image = convertView.findViewById(R.id.list_item_icon);
if(item.getResourceID() == -1) {
image.setVisibility(View.GONE);
} else {
image.setImageResource(item.getResourceID());
}
TextView miwokWord = convertView.findViewById(R.id.miwok_word);
miwokWord.setText(item.getMiwokTranslation());
miwokWord.setTextColor(color);
TextView defaultWord = convertView.findViewById(R.id.default_word);
defaultWord.setText(item.getDefaultTranslation());
defaultWord.setTextColor(color);
ImageButton button = convertView.findViewById(R.id.imageButton);
MediaPlayer mediaPlayer = MediaPlayer.create(context, item.getAudioID());
button.setOnClickListener(v -> {
if (!mediaPlayer.isPlaying()) {
button.setImageResource(R.drawable.play_icon);
mediaPlayer.start();
} else {
button.setImageResource(R.drawable.pause_icon);
mediaPlayer.pause();
}
});
return convertView;
}
}
The Annotations are these due to previous efforts and I didn't remove them, in case i'd need them again.
Last but not least, here is the xml of the adapter:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:minHeight="?android:attr/listPreferredItemHeight"
android:padding="16dp"
android:focusable="true"
android:focusableInTouchMode="false">
<ImageView
android:id="#+id/list_item_icon"
android:layout_width="88dp"
android:layout_height="88dp"
android:contentDescription="#string/magic"
android:background="#424242"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:paddingStart="16dp"
tools:ignore="RtlSymmetry">
<TextView
android:id="#+id/miwok_word"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:textStyle="bold"/>
<TextView
android:id="#+id/default_word"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
<ImageButton
android:id="#+id/imageButton"
android:layout_width="73dp"
android:layout_height="match_parent"
android:contentDescription="#string/playsound"
android:src="#drawable/play_icon"/></LinearLayout>
I have been sitting on this for some good couple of hours by now without any significant progress and at this Point i don't have any clues about what to do next.
Any Help would be appreciated.
Thanks in Advance
Not sure why you concluded that focus has anything to do with your problem.
If the default beginning state of the icon is android:src="#drawable/play_icon" and the default beginning state of the mediaPlayer is "not playing", wouldn't the first click result in button.setImageResource(R.drawable.play_icon); which just...sets the play icon again? So the first click changes the icon from play to play, and the second sets it from play to pause.
Have you tried debugging your code with a breakpoint? Set one in your click listener and see what happens.
Related
I have created a study helper app for android. I use a custom array adapter that has a checkbox and a textview in each row. Some of my listviews are populated using this custom adapter. My listviews are used to navigate to other activities, and have onItemClick listeners.
On the android studio emulator, everything works fine. However, I exported the apk and installed it on my phone, and the listviews using my custom adapter no longer did anything on click.
Here is my custom adapter:
public class CheckboxAdapter extends BaseAdapter {
private Context context;
ArrayList<String[]> list = new ArrayList<>();
Boolean completed[];
public CheckboxAdapter(ArrayList<String[]> list,Context context) {
super();
this.context = context;
this.list = list;
completed = new Boolean[list.size()];
for (int i = 0; i < completed.length; i++){
if(list.get(i)[1].equalsIgnoreCase("true")){
completed[i] = true;
} else {
completed[i] = false;
}
}
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int position) {
return list.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
// Class to temporarily store the textview and checkbox in each row
public class ViewHolder {
public TextView nametext;
public CheckBox tick;
}
// Override getView method to set custom row layout
// Use viewHolder to get the textview and checkbox then inflate it
// Set text to passed in list of string data
// Set checkbox to passed in array of booleans, then disable the checkbox
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder view = null;
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
if (view == null) {
view = new ViewHolder();
convertView = inflater.inflate( R.layout.checkbox_adapter, null);
view.nametext = (TextView) convertView.findViewById(R.id.adaptertextview);
view.tick = (CheckBox)convertView.findViewById(R.id.adaptercheckbox);
convertView.setTag(view);
} else {
view = (ViewHolder) convertView.getTag();
}
view.tick.setTag(position);
view.nametext.setText(list.get(position)[0]);
view.tick.setChecked(completed[position]);
view.tick.setEnabled(false);
return convertView;
}
}
And its XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent">
<CheckBox
android:id="#+id/adaptercheckbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/adaptertextview"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Here is an example of a listview using the custom adapter, and its onclick function:
ArrayList<String[]> content = new ArrayList<String[]>();
content.add(new String[] {"Lesson 1 Highest Mark: " + highest[0], completed[0]});
content.add(new String[] {"Lesson 2 Highest Mark: " + highest[1], completed[1]});
content.add(new String[] {"Lesson 3 Highest Mark: " + highest[2], completed[2]});
content.add(new String[] {"Lesson 4 Highest Mark: " + highest[3], completed[3]});
content.add(new String[] {"Lesson 5 Highest Mark: " + highest[4], completed[4]});
content.add(new String[] {"Combined Quiz", "false"});
ListView quizList = (ListView) findViewById(R.id.quizListView);
CheckboxAdapter adapter = new CheckboxAdapter(content, this);
quizList.setAdapter(adapter);
quizList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
System.out.println(parent. getItemAtPosition(position));
switch (position) {
case 0: Intent i0 = new Intent(Quiz.this, Quiz1.class);
startActivity(i0);
break;
case 1: Intent i1 = new Intent(Quiz.this, Quiz2.class);
startActivity(i1);
break;
case 2: Intent i2 = new Intent(Quiz.this, Quiz3.class);
startActivity(i2);
break;
case 3: Intent i3 = new Intent(Quiz.this, Quiz4.class);
startActivity(i3);
break;
case 4: Intent i4 = new Intent(Quiz.this, Quiz5.class);
startActivity(i4);
break;
case 5: Intent i5 = new Intent(Quiz.this, QuizCombined.class);
startActivity(i5);
break;
default: return;
}
}
});
Any ideas why this only works on the android studio emulator? I've tried on two devices and Memu emulator but it didn't work on any of them, only the android studio emulator.
EDIT: the xml for the activity using the above listview
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Quiz">
<TextView
android:id="#+id/quizTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:layout_marginTop="56dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/quizTextView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/quizTextView" />
<ListView
android:id="#+id/quizListView"
android:layout_width="368dp"
android:layout_height="493dp"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/quizTextView2" />
</android.support.constraint.ConstraintLayout>
<include
layout="#layout/app_bar_main_menu"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main_menu"
app:menu="#menu/activity_main_menu_drawer" />
</android.support.v4.widget.DrawerLayout>
EDIT: I copied the project to my laptop and ran it in the emulator there, and it didn't work. Seems like it ONLY works on my pc
remove the duplicate
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
from the android.support.constraint.ConstraintLayout.
most likely a transparent layout overlaps and prevents clicking...
the inspect view boundaries button is tacked away in the tiles;
think it's also available in the developer settings.
I have a ListView that shows list items (duh). When you click on a list item, another Activity opens. Part of the list item layout is a grey star, an ImageView. When you click on this ImageView, I don't want to open another Activity, but I want to change the color of the star to green (= mark the item as favourite) or back (= mark it as not favourite). I managed to do that with an OnClickListener, loading another ImageView on Click, and refreshing the adapter. But for the ImageView to change, after clicking it I need to leave the Activity and enter again. It doesn't refresh instantly. Why, and how can I change that? I've tried lots of different versions, so far nothing works. My ListViewAdapter extends BaseAdapter. Thank you!
public class ListViewAdapterKeysAToZ extends BaseAdapter {
private ArrayList<KeyTagIntern> keyTags;
private ObservableArrayList<KeyTagIntern> list;
private Context context;
TextView name;
TextView place;
ImageView star, favoriteStar;
public ListViewAdapterKeysAToZ(Context context, ObservableArrayList<KeyTagIntern> list)
{
this.context = context;
this.list = list;
keyTags = new ArrayList<>();
for (KeyTagIntern keytag : list) {
keyTags.add(keytag);
}
//(....)
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
KeyTagIntern key = (KeyTagIntern) getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.list_item_keys, parent, false);
}
name = (TextView) convertView.findViewById(R.id.text_keylist_item);
name.setText(key.getName());
place = (TextView) convertView.findViewById(R.id.text_keylist_item_place);
place.setText(key.getPlace());
star = (ImageView) convertView.findViewById(R.id.right_icon_keylist_item);
favoriteStar = (ImageView) convertView.findViewById(R.id.right_icon_keylist_item_favorite);
if (key.isFavorite())
{
star.setVisibility(View.INVISIBLE);
favoriteStar.setVisibility(View.VISIBLE)
favoriteStar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// This makes key.isFavourite() = false for the next time
Paper.book().delete(FAVORIT + String.valueOf(key.getKeyTagID()));
//Since notifyDataSetChanged() didn't work for me, I tried this - but no change
int index = list.indexOf(key);
list.remove(index);
list.add(index, key);
keyTags = new ArrayList<>();
for (KeyTagIntern keytag : list) {
keyTags.add(keytag);
}
notifyDataSetChanged();
}
});
}
// Then do the opposite for if (!key.isFavourite())
Und hier das xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/list_item_keys"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#color/MiddleDarkGrey">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/btn_list_item_keys"
android:layout_width="match_parent"
android:layout_height="#dimen/height_list_item"
android:layout_marginBottom="3dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="3dp"
android:background="#drawable/white_list_item"
android:paddingLeft="13dp"
android:paddingRight="10dp">
<ImageView
android:id="#+id/icon_keylist_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:visibility="visible"
app:srcCompat="#drawable/ic_key" />
<ImageView
android:id="#+id/icon_reserved"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/chb_add_key"
android:layout_centerVertical="true"
android:visibility="invisible"
app:srcCompat="#drawable/ic_reservate_orange" />
<ImageView
android:id="#+id/icon_taken"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/chb_add_key"
android:layout_centerVertical="true"
android:visibility="invisible"
app:srcCompat="#drawable/ic_taken_red" />
<TextView
android:id="#+id/text_keylist_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:layout_toEndOf="#+id/icon_keylist_item"
android:layout_toRightOf="#+id/icon_keylist_item"
android:gravity="center_vertical"
android:layout_centerVertical="true"
android:text="Text"
android:textColor="#color/DarkGrey"
android:textSize="#dimen/text_list_item" />
<TextView
android:id="#+id/text_keylist_item_place"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/text_keylist_item"
android:layout_alignLeft="#+id/text_keylist_item"
android:layout_marginLeft="2dp"
android:layout_marginBottom="5dp"
android:text="Where is the key?"
android:textColor="#color/DarkGrey"
android:textSize="#dimen/text_list_item_sub" />
<ImageView
android:id="#+id/right_icon_keylist_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
app:srcCompat="#drawable/ic_fav_green" />
<ImageView
android:id="#+id/right_icon_keylist_item_favorite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="#drawable/ic_fav_chosen"
android:visibility="invisible"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
</RelativeLayout>
I think your approach should be something like this.
rather hiding and displaying an image just change source of it!
if (key.isFavorite())
{
favoriteStar.setImageResource(R.drawable.aaa);
favoriteStar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
favoriteStar.setImageResource(R.drawable.bbb);
// and vice-versa
and I don't thing you will be needing notifyDataSetChanged(); as you are making no changes in the Listdata actually!
In the end the answer was rather stupid, as it is so often, and you guys couldn't have helped me since I excluded the code at the beginning of my adapter class (added it now). It actually worked the whole time, but I didn't see it, since the listitem at the very end of the list was changed, not the selected one. This was due to me declaring the variables at the beginning of the adapter class, rather than inside the getView method.
I changed it to this and now it works perfectly:
public class ListViewAdapterKeysAToZ extends BaseAdapter {
private ArrayList<KeyTagIntern> keyTags;
private ObservableArrayList<KeyTagIntern> list;
private Context context;
public ListViewAdapterKeysAToZ(Context context, ObservableArrayList<KeyTagIntern> list) {
this.context = context;
this.list = list;
keyTags = new ArrayList<>();
for (KeyTagIntern keytag : list) {
keyTags.add(keytag);
}
// (...)
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
KeyTagIntern key = (KeyTagIntern) getItem(position);
TextView name;
TextView place;
ImageView star, favoriteStar;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.list_item_keys, parent, false);
}
name = (TextView) convertView.findViewById(R.id.text_keylist_item);
name.setText(key.getName());
place = (TextView) convertView.findViewById(R.id.text_keylist_item_place);
place.setText(key.getPlace());
star = (ImageView) convertView.findViewById(R.id.right_icon_keylist_item);
favoriteStar = (ImageView) convertView.findViewById(R.id.right_icon_keylist_item_favorite);
if (key.isFavorite()) {
star.setVisibility(View.INVISIBLE);
favoriteStar.setVisibility(View.VISIBLE);
}else {
star.setVisibility(View.VISIBLE);
favoriteStar.setVisibility(View.INVISIBLE);
}
star.setOnClickListener(v -> {
key.setFavorite(true);
Paper.book().write(FAVORIT + String.valueOf(key.getKeyTagID()), true);
notifyDataSetChanged();
});
favoriteStar.setOnClickListener(v -> {
key.setFavorite(false);
Paper.book().delete(FAVORIT + String.valueOf(key.getKeyTagID()));
notifyDataSetChanged();
});
I am using the listView widget on android, and in preview list content I chose "checked list" item
Basically it is a list of items and I should be able to check some items and when I do the check mark next to the item becomes visible (it isn't a checkbox, that is the difference between many other checkable lists)
I don't know how to use it, I would like to know at least how I can check some item, that is make the check mark visible, because when I click on an item, it is clickable but nothing happens...
image of listview in simulator
image of listview in editor
here is my xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:rsb="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:background="#fffefdff">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="540dp"
android:weightSum="1"
android:id="#+id/linearLayoutPreferences"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:focusableInTouchMode="false"
android:divider="#ff080808"
android:dividerPadding="#dimen/activity_horizontal_margin"
android:showDividers="middle|beginning|end">
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/listView"
tools:listitem="#android:layout/simple_list_item_checked"
android:clickable="true"
android:fastScrollAlwaysVisible="false"
android:choiceMode="multipleChoice"
android:contextClickable="false" />
</LinearLayout>
here is my java file
public class Popneighbourhood extends AppCompatActivity {
ListView listNeighbourhood;
String[] neighbourhood = new String[]{
"Alamo Square/NOPA", "Castro/Upper Market", "Central Richmond", "Cole Valley/Ashbury Heights", "Downtown/Civic/Van Ness", "Duboce Triangle",
"Financial District", "Glen Park", "Haight Ashbury", "Hayes Vallez", "Ingleside/SFSU/CCSF", "Inner Richmond",
"Inner Sunset/UCSF", "Jordan Park/Laurel Heights", "Laurel Heights/Presidio", "Lower Haight", "Lower Nob Hill", "Lower Pac Heights",
"Marina/Cow Hollow", "Mission Bay", "Mission District", "Nob Hill", "Noe Valley", "North Beach/Telegraph Hill",
"Oakland North/Temescal", "Pacific Heights"
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_popneighbourhood);
ActionBar actionBar=getSupportActionBar();
actionBar.setDisplayShowHomeEnabled(true);
actionBar.setIcon(R.mipmap.logofrontdoor);
listNeighbourhood = (ListView) findViewById(R.id.listView);
//android.R.layout.simple_list_item_1 est une vue disponible de base dans le SDK android,
//Contenant une TextView avec comme identifiant "#android:id/text1"
ArrayAdapter<String> adapter = new ArrayAdapter<String>(Popneighbourhood.this,
android.R.layout.simple_list_item_1, neighbourhood);
listNeighbourhood.setAdapter(adapter);
//adapter code , i just took one of the adapter source from my project, notice the imageView, iv_item_fragment_dashboard_country_list_select, is toggled when you select.
public class DashboardCountryListAdapter extends BaseAdapter {
private Context mContext;
private List<Country> mCountryList = new ArrayList<>();
public DashboardCountryListAdapter(Context context, List<Country> countryList) {
mContext = context;
mCountryList = countryList;
}
#Override
public int getCount() {
return mCountryList.size();
}
#Override
public Object getItem(int position) {
return mCountryList.isEmpty() ? null : mCountryList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.fragment_dashboard_country_list, parent, false);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
if (!mCountryList.isEmpty()) {
Country country = mCountryList.get(position);
int image = country.getImage();
if (image != -1) {
viewHolder.iv_item_fragment_dashboard_country_list.setImageResource(image);
if (country.getSelected()){
viewHolder.iv_item_fragment_dashboard_country_list_select.setVisibility(View.VISIBLE);
}
else
viewHolder.iv_item_fragment_dashboard_country_list_select.setVisibility(View.GONE);
}
viewHolder.tv_item_fragment_dashboard_country_list.setText(country.getName());
}
return convertView;
}
class ViewHolder {
#Bind(R.id.iv_item_fragment_dashboard_country_list)
ImageView iv_item_fragment_dashboard_country_list;
#Bind(R.id.tv_item_fragment_dashboard_country_list)
TextView tv_item_fragment_dashboard_country_list;
#Bind(R.id.iv_item_fragment_dashboard_country_list_select)
ImageView iv_item_fragment_dashboard_country_list_select;
public ViewHolder(View view) {
ButterKnife.bind(this, view);
}
}
public void updateList(List<Country> list) {
mCountryList = list;
notifyDataSetChanged();
}
}
//xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="50dp">
<ImageView
android:id="#+id/iv_item_fragment_dashboard_country_list"
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:adjustViewBounds="true"
android:layout_width="20dp"
android:layout_height="15dp" />
<com.UTU.View.UtuTextView
android:id="#+id/tv_item_fragment_dashboard_country_list"
android:textColor="#color/chic_black"
android:textSize="18sp"
android:gravity="center_vertical"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<ImageView
android:id="#+id/iv_item_fragment_dashboard_country_list_select"
android:src="#drawable/icon_check_teal"
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:adjustViewBounds="true"
android:layout_width="13dp"
android:layout_height="10dp" />
</LinearLayout>
I can tell you why the editor looks different from the running app:
In your layout XML the list view has this attribute:
tools:listitem="#android:layout/simple_list_item_checked"
but in your code you have
ArrayAdapter<String> adapter = new ArrayAdapter<String>(Popneighbourhood.this,
android.R.layout.simple_list_item_1, neighbourhood);
so you're using an entirely different layout for the list item.
You need to put R.layout.simple_list_item_checked in the adapter constructor, and you will probably need to change to the constructor that specifies the id of the TextView to use.
I have a ListView in one of my activities that I have bound to an ArrayList using a custom ArrayAdapter. I have set an OnItemClickListener to the ListView which should call a method that starts another activity. However, I find that when I click on the ListView items, it only sometimes works. Sometimes it will start the activity as it should; other times it seems to detect the click (the ripple effect appears on the list item) but does nothing; other times it doesn't even appear to detect the click (the ripple effect doesn't appear).
I've tried all the usual suggestions that I've come across: blocking descendants on the parent view item, setting clickable and focusable to false on all the components of the item views, setting isEnabled to return true in the custom adapter, etc, but the behavior remains the same. Any help appreciated. Here is the relevant code:
Activity containing the ListView:
public class ViewCollectionActivity extends AppCompatActivity {
private final String className = this.getClass().getSimpleName();
private CollectionHandler collectionHandler;
private Context context;
private ArrayList<Game> displayedCollection;
private GameCollectionAdapter collectionAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_collection);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
context = this;
collectionHandler = CollectionHandler.getInstance(this);
TextView view = null;
if (collectionHandler.getDisplayedCollection().size() > 0) {
view = (TextView) findViewById(R.id.no_items_textview);
view.setVisibility(View.GONE);
}
String currentDate = collectionHandler.getDateLastSynchronised();
view = (TextView) findViewById(R.id.last_updated_textview);
view.setText("Last synchronised: " + currentDate + " Total games: " + String.valueOf(collectionHandler.getDisplayedCollection().size()));
collectionAdapter = collectionHandler.getCollectionAdapter();
ListView listView = (ListView) findViewById(R.id.collection_list_view);
listView.setAdapter(collectionAdapter);
AdapterView.OnItemClickListener collectionItemClickListener = new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
launchGameDetailsActivity(position);
}
};
listView.setOnItemClickListener(collectionItemClickListener);
}
public void launchGameDetailsActivity(int position){
Log.d(className,"Starting lauchGameDetailsActivity method");
collectionHandler.setSelectedGame(position);
Intent intent = new Intent(this,ViewGameDetailsActivity.class);
startActivity(intent);
Log.d(className, "Ending lauchGameDetailsActivity method");
}
The XML for the activity:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.bleachedlizard.ludome.viewcollection.ViewCollectionActivity">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Synchronise Collection"
android:onClick="synchroniseCollection"/>
<TextView
android:id="#+id/last_updated_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Last synchronised: "
android:textAlignment="center"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Display Collection"
android:visibility="gone"
android:onClick="displayCollection"/>
<ListView
android:id="#+id/collection_list_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</ListView>
<TextView
android:id="#+id/no_items_textview"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="You have no items in your collection."
android:textAlignment="center"
android:textSize="20sp"/>
</LinearLayout>
The XML for the item views:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/collection_item_layout"
android:layout_width="match_parent"
android:layout_height="75dp"
android:orientation="horizontal"
android:clickable="false"
android:descendantFocusability="blocksDescendants"
android:focusable="false"
android:focusableInTouchMode="false">
<ImageView
android:id="#+id/collection_item_image"
android:layout_width="75dp"
android:layout_height="75dp"
android:src="#drawable/testimage"
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="false"
/>
<TextView
android:id="#+id/collection_item_name"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:padding="16dp"
android:singleLine="false"
android:textColor="#android:color/darker_gray"
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="false"
android:textIsSelectable="false"/>
<TextView
android:id="#+id/collection_item_plays"
android:layout_width="100dp"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:padding="8dp"
android:textColor="#android:color/darker_gray"
android:text="Plays: 0"
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="false"
android:textIsSelectable="false"/>
</LinearLayout>
The code for the custom adapter:
public class GameCollectionAdapter extends ArrayAdapter<Game> {
private ArrayList<Game> collection;
public GameCollectionAdapter(Context context, int resource, ArrayList<Game> collection){
super(context, resource, collection);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout gameView = (LinearLayout) convertView;
LayoutInflater mInflater = LayoutInflater.from(getContext());
if (gameView == null) {
gameView = (LinearLayout) mInflater.inflate(R.layout.collection_item_view, null);
}
//Game game = collection.get(position);
Game game = super.getItem(position);
if (game != null) {
// This is how you obtain a reference to the TextViews.
// These TextViews are created in the XML files we defined.
TextView gameTitle = (TextView) gameView.findViewById(R.id.collection_item_name);
TextView numOfPlays = (TextView) gameView.findViewById(R.id.collection_item_plays);
ImageView thumbnail = (ImageView) gameView.findViewById(R.id.collection_item_image);
// check to see if each individual textview is null.
// if not, assign some text!
if (gameTitle != null){
gameTitle.setText(game.getTitle());
}
if (numOfPlays != null){
numOfPlays.setText("Plays: " + String.valueOf(game.getNumOfPlays()));
}
if (thumbnail != null){
thumbnail.setImageBitmap(game.getThumbnail());
}
}
// the view must be returned to our activity
return gameView;
}
#Override
public boolean isEnabled(int position) {
return true;
}
}
I discovered what was causing the problem: the way I had set up the array that backed the ListView meant that it was downloading and storing the Bitmaps for every element in the array all the time. Once I changed the implementation so that it only downloaded the images as the ListView required them, then that seemed to improve performance and the onClickListener started to work fine.
The implementation I used was the exact same one shown here:
http://developer.android.com/training/displaying-bitmaps/process-bitmap.html
I think the issue is due to the position of the item selection whenever you click you have an list position which is passed to your method launchGameDetailActivity(int position) check with log or toast on item click what all the position you are getting do the needful.
Here is my code try this like this if it helps.
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(RecipeClass.this, "Position is" + position, Toast.LENGTH_SHORT).show();
Intent intent = new Intent(RecipeClass.this, RecipeIngredients.class)
intent.putExtra("position", position);
startActivity(intent);
}
Check your arraylist value also whether they are not null.
I am trying to use Cardslib to create a RecyclerView with custom layout rows that would expand when I click a button on them. I followed customization guide and create both custom layout and custom card class, the cards do appear correctly like this
but I cant figure out how to set clicking event for view elements on this card.
In activity_main.xml, I have a CardRecyclerView:
<it.gmariotti.cardslib.library.recyclerview.view.CardRecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
card:list_card_layout_resourceID="#layout/my_cardview_layout"
android:id="#+id/my_recyclerview"/>
my_cardview_layout.xml:
<it.gmariotti.cardslib.library.view.CardViewNative xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card="http://schemas.android.com/apk/res-auto"
android:id="#+id/list_cardId"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
card:card_layout_resourceID="#layout/my_material_card_layout"
style="#style/card_external"
android:layout_marginTop="12dp" />
my_material_card_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<it.gmariotti.cardslib.library.view.ForegroundLinearLayout
android:id="#+id/card_main_layout"
style="#style/card.native.main_layout_foreground"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:layout_width="match_parent"
android:layout_height="210dp"
android:id="#+id/mycard_image"
android:src="#drawable/sea"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Title"
android:id="#+id/mycard_title"
android:paddingTop="24dp"
android:paddingLeft="20dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Subtitle"
android:id="#+id/mycard_subtitle"
android:paddingLeft="20dp" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/actions_padding"
android:paddingLeft="#dimen/actions_padding_left"
android:paddingRight="#dimen/actions_padding_left">
<TextView
android:id="#+id/mycard_suppaction1"
android:text="SHARE"
android:background="?android:selectableItemBackground"
android:layout_width="wrap_content"
style="#style/card.native.actions"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/mycard_suppaction2"
android:text="LEARN MORE"
android:background="?android:selectableItemBackground"
android:layout_width="wrap_content"
style="#style/card.native.actions"
android:layout_height="wrap_content"/>
</LinearLayout>
</it.gmariotti.cardslib.library.view.ForegroundLinearLayout>
<FrameLayout
android:id="#+id/card_content_expand_layout"
style="#style/card.native.main_contentExpand"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
</FrameLayout>
My main activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayList<Card> cards = new ArrayList<Card>();
//CardViewNative cardView = (CardViewNative) findViewById(R.id.myMaterialCardView);
for(int i = 0; i<3; i++) {
MyMaterialCard card = new MyMaterialCard(this);
CardExpand expand = new CardExpand(getApplicationContext());
//Set inner title in Expand Area
expand.setTitle(" Hidden content");
card.addCardExpand(expand);
card.setId("" + i);
cards.add(card);
}
CardArrayRecyclerViewAdapter mCardArrayAdapter = new CardArrayRecyclerViewAdapter(this, cards);
//Staggered grid view
CardRecyclerView mRecyclerView = (CardRecyclerView) this.findViewById(R.id.my_recyclerview);
mRecyclerView.setHasFixedSize(false);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
//Set the empty view
if (mRecyclerView != null) {
mRecyclerView.setAdapter(mCardArrayAdapter);
}
}
my custom card class:
public class MyMaterialCard extends Card {
ImageView mImage;
TextView mTitle;
TextView mSubtitle;
TextView mActionButton1;
TextView mActionButton2;
public MyMaterialCard(Context context) {
super(context, R.layout.my_cardview_layout);
}
public MyMaterialCard(Context context, int innerLayout) {
super(context, innerLayout);
}
#Override
public void setupInnerViewElements(ViewGroup parent, View view) {
mImage = (ImageView) view.findViewById(R.id.mycard_image);
mTitle = (TextView) view.findViewById(R.id.mycard_title);
mSubtitle = (TextView) view.findViewById(R.id.mycard_subtitle);
mActionButton1 = (TextView) view.findViewById(R.id.mycard_suppaction1);
mActionButton2 = (TextView) view.findViewById(R.id.mycard_suppaction2);
mActionButton1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getContext(), "action 1", Toast.LENGTH_SHORT).show();
}
});
ViewToClickToExpand viewToClickToExpand =
ViewToClickToExpand.builder()
.setupView(mActionButton2);
setViewToClickToExpand(viewToClickToExpand);
}}
I think the problem maybe the my_cardview_layout.xml, however, if i set card:list_card_layout_resourceID="#layout/my_material_card_layout"
in recyclerview and
public MyMaterialCard(Context context) {
super(context, R.layout.my_material_card_layout);}
they will not appear as cards:
have been working on this for 2 days and still can not get those buttons to work ( tried using Cardslib material card but when add expand, nothing happened). Really appreciate any help, thank you!
On main activity, add function setOnClickListener:
for(int i = 0; i<3; i++) {
MyMaterialCard card4 = new MyMaterialCard(this);
card.setOnClickListener(new Card.OnCardClickListener() {
#Override
public void onClick(Card card, View view) {
Toast.makeText(view.getContext()," Click on ActionArea ",Toast.LENGTH_SHORT).show();
}
});
CardExpand expand = new CardExpand(getApplicationContext());
//Set inner title in Expand Area
expand.setTitle(" Hidden content");
card.addCardExpand(expand);
card.setId("" + i);
cards.add(card4);
}
I think this could help some people, I hope not you xD (1 year, 10 months ago)