ActionBarSherlock setCustomView not working in Android 3.2 - android

I recently upgraded my application to use ActionBarSherlock 4.1. Since the upgrade users running the app on Honeycomb experiance a force close due to a null pointer exception when setting a custom view on the actionbar.
I add a custom view containing two spinners to the actionbar this works on Android 4.0 & 4.1 but is not working on 3.2.
bar.setCustomView(R.layout.custom_action_bar);// spinners
actionBarViewHolder= new CustomActionBarViewHolder();
actionBarViewHolder.categorySpinner = (Spinner) findViewById(R.id.actionbar_catergory);
actionBarViewHolder.sortBySpinner = (Spinner) findViewById(R.id.actionbar_sortby);
On Android 3.2 the spinners can not be found yet on 4.0 and 4.1 they views are found and anything runs smoothly.
I have not tried the application on a 3.0 emulator but I image the problem persists.
Any ideas what could be the problem?
<LinearLayout android:id="#+id/linearLayout1"
android:layout_width="wrap_content" android:layout_height="match_parent"
android:gravity="center_vertical|center_horizontal"
android:layout_weight="0.5">
<TextView android:id="#+id/textView1" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Category:" />
<Spinner android:id="#+id/actionbar_catergory"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:entries="#array/actionbar_spinner_catergory"
android:background="#drawable/spinner_background" />
</LinearLayout>
<LinearLayout android:id="#+id/linearLayout1"
android:layout_width="wrap_content" android:layout_height="match_parent"
android:gravity="center_vertical|center_horizontal"
android:layout_weight="0.5">
<TextView android:id="#+id/textView2" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Sort By:" />
<Spinner android:id="#+id/actionbar_sortby"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:entries="#array/actionbar_spinner_sortby" android:background="#drawable/spinner_background" />
</LinearLayout>

Try this, its working fine on all devices or you can check the demo code here
getSupportActionBar().setCustomView(R.layout.actionbar_top); // load your layout
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
Images

Try this:
final View view = inflater.inflate(R.layout.custom_action_bar, null);
bar.setCustomView(view);// spinners
actionBarViewHolder= new CustomActionBarViewHolder();
actionBarViewHolder.categorySpinner = (Spinner) view.findViewById(R.id.actionbar_catergory);
actionBarViewHolder.sortBySpinner = (Spinner) view.findViewById(R.id.actionbar_sortby);

Here is code how I create custom action bar with actiobBarSherlock
private void createCustomActionBar() {
List<SiteLink> links = new ArrayList<SiteLink>();
links.add(...)
LinksAdapter linkAdapter = new LinksAdapter(this, R.layout.external_link, links);
View customNav = LayoutInflater.from(this).inflate(R.layout.custom_show_action_bar, null);
IcsSpinner spinner = (IcsSpinner)customNav.findViewById(R.id.spinner);
spinner.setAdapter(linkAdapter);
ImageView refresh = (ImageView) customNav.findViewById(R.id.refresh);
refresh.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
...
}
});
ImageView settings = (ImageView) customNav.findViewById(R.id.settings);
settings.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
...
}
});
getSupportActionBar().setCustomView(customNav, new ActionBar.LayoutParams(Gravity.RIGHT));
getSupportActionBar().setDisplayShowCustomEnabled(true);
}
Adapter
private static class LinksAdapter extends ArrayAdapter<SiteLink> {
private List<SiteLink> strings;
private Context context;
private LinksAdapter(Context context, int textViewResourceId, List<SiteLink> objects) {
super(context, textViewResourceId, objects);
this.strings = objects;
this.context = context;
}
#Override
public int getCount() {
if (strings == null) return 0;
return strings.size();
}
#Override
public SiteLink getItem(int position) {
return super.getItem(position);
}
// return views of drop down items
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
final SiteLink siteLink = strings.get(position);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// at 0 position show only icon
TextView site = (TextView) inflater.inflate(R.layout.external_link, null);
site.setText(siteLink.getName());
site.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(siteLink.getUrl()));
context.startActivity(i);
}
});
return site;
}
// return header view of drop down
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
return inflater.inflate(R.layout.icon, null);
}
}
Layout
<?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:gravity="right"
>
<com.actionbarsherlock.internal.widget.IcsSpinner
android:id="#+id/spinner"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingRight="20dp"
android:layout_gravity="center"
/>
<ImageView android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="#drawable/ic_navigation_refresh"
android:paddingRight="20dp"
android:paddingLeft="10dp"
android:layout_gravity="center"
android:background="#drawable/action_buttons_background"
android:id="#+id/refresh"/>
<ImageView android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="#drawable/ic_action_settings"
android:paddingRight="20dp"
android:background="#drawable/action_buttons_background"
android:layout_gravity="center"
android:id="#+id/settings"/>
</LinearLayout>

Have you tried to put your two children LinearLayout's inside a main LinearLayout?. Also try to not repeat the id from the children LinearLayout's, because you're making your id's system cry. But I'm almost sure your problem is that you have more than one main Layouts in the XML file.

Use below code for setCustomView using actionbarsherlib.
It is worked in android 3.2 version also.
getSupportActionBar().setDisplayShowCustomEnabled(true);
View view = getLayoutInflater().inflate(R.layout.custom_view, null);
Button mybutton = (Button)view.findViewById(R.id.button1);
mybutton.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
/** Your click actions here. */
}
});
getSupportActionBar().setCustomView(view);

This is my code.here I added Sherlock bar library to my project.then, I used here for set my Title on header(Top). like this..
just try this like.. Set target SDK to Android 3.2(Version 14) or above..
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
getSupportActionBar().setCustomView(R.layout.header_sherlock_xmllayout);
header_tvleft = (TextView) findViewById(R.id.header_tvleft);
header_tvleft.setText("Back");
try this method....

Related

How to change an ImageView, that is part of a list item?

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();
});

Android - OnItemClickListener only *sometimes* not working

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.

Fragment disappears after setAdapter on ListView

I have a ListView in a Fragment containing also some other UI-Elements. Everything works until I call setAdapter on the ListView. In that moment I can debug that the ListView is filled with the elements but immmediately after the whole fragment disappears (including the other UI-Elements). If I set the Adapter 0,1 seconds later, everything works.
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.fragment_listview, null);
mListView = (ListView)mView.findViewById(R.id.list_items);
TextView emptyView = (TextView)mView.findViewById(R.id.text_empty);
mListView.setEmptyView(emptyView);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
// this is the only work around to not make the list view disappear
loadContacts();
}
}, 100);
// if I call loadContacts() here, the Fragment disappears
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Person p = mContacts.get(position);
if (pickerInterface != null) {
pickerInterface.pickedContact(p);
}
}
});
return mView;
}
public void loadContacts() {
mContacts = ContactsDataSource.getAllPhoneContacts(getActivity(), true);
mAdapter = new ContactsAdapter(getActivity());
mAdapter.mContacts = mContacts;
mAdapter.isPlainList = true;
// after the following line the Fragment is filled and then immediately disappears
mListView.setAdapter(mAdapter);
}
the ContactsAdapter is very simple:
public class ContactsAdapter extends BaseAdapter {
public List<Person> mContacts = new ArrayList<Person>();
public Activity context;
// Constructor
public ContactsAdapter(Activity c){
context = c;
}
#Override
public int getCount() {
return mContacts.size();
}
public Person getItem(int position){
return mContacts.get(position);
}
#Override
public boolean isEmpty()
{
return mContacts.size() == 0;
}
#Override
public long getItemId(int position) {
return position;
}
#SuppressLint("InflateParams")
public View getView(int position, View convertView, ViewGroup viewGroup) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_item_contact, null);
}
Person person = mContacts.get(position);
TextView tvName = (TextView) convertView.findViewById(R.id.text_name);
tvName.setText(person.getDisplayName());
return convertView;
}
}
I have spent hours debugging and searching for reasons and have no clue. Thanks for any idea.
Edit: XML as following:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white" >
<ListView
android:id="#+id/list_items"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/line_horizontal"
android:layout_alignParentTop="true" />
<TextView
android:id="#+id/text_empty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="15dp"
android:layout_alignParentTop="true"
android:text="#string/label_no_entries"
android:textColor="#color/grey"
android:textSize="21sp" />
<View
android:id="#+id/line_horizontal"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_above="#+id/layout_navigation"
android:background="#color/black" />
<RelativeLayout
android:id="#+id/layout_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" >
<TextView
android:id="#+id/text_scrollback"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:drawablePadding="10dp"
android:drawableRight="#drawable/backward"
android:gravity="center_vertical"
android:paddingBottom="15dp"
android:paddingLeft="10dp"
android:paddingTop="15dp"
android:text="#string/activity_contacts_backward_label"
android:textColor="#color/mediumgrey" />
<View
android:id="#+id/view_coverback"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/text_scrollback"
android:layout_alignParentLeft="true"
android:layout_alignRight="#+id/text_scrollback"
android:layout_alignTop="#+id/text_scrollback"
android:background="#c0ffffff" />
<TextView
android:id="#+id/text_scrollforward"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:drawableLeft="#drawable/forward"
android:drawablePadding="10dp"
android:gravity="center_vertical"
android:paddingBottom="15dp"
android:paddingRight="10dp"
android:paddingTop="15dp"
android:text="#string/activity_contacts_forward_label"
android:textColor="#color/mediumgrey" />
<View
android:id="#+id/view_coverforward"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/text_scrollforward"
android:layout_alignParentRight="true"
android:layout_alignLeft="#+id/text_scrollforward"
android:layout_alignTop="#+id/text_scrollforward"
android:background="#c0ffffff" />
<TextView
android:id="#+id/text_pages"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/text_scrollforward"
android:layout_toLeftOf="#+id/text_scrollforward"
android:layout_toRightOf="#+id/text_scrollback"
android:gravity="center"
android:textColor="#color/mediumgrey"
android:textSize="17sp" />
</RelativeLayout>
</RelativeLayout>
Where did you initialize your "mListView"?
The time that fragment inflated is "onCreateView()" and general way of getting view instances from layout is done on this method. like below
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_one, null);
mListView = (ListView)v.findViewById(R.id.list_items);
...
return v;
}
How about trying to initalize your views(ListViews, and others) in "onCreateView"?
I think that the problem is caused from getting view instances before fragment is inflated.
Not sure what your problem is. May be with the custom super class. Otherwise, wild guess here, but try inflating your view like this.
mView = inflater.inflate(R.layout.fragment_listview, container, false);
First of all, storing a context object can be dangerous and should therefore be avoided if possible... You can easily get rid of it in your adapter with following steps (that hopefully also solves your problem):
--> try following constructor for your adapter:
public ContactsAdapter(Context c){
super(c, R.layout.yourlayout_listitem_name;
}
--> and adjust the getView-method to use something like:
final View rowView = View.inflate(viewGroup.getContext(), R.layout.yourlayout_listitem_name, null);
instead of the inflater-if-block. then always return rowView at the end.
and just to be sure I would remove the overriden-method:
#Override
public long getItemId(int position) {
return position;
}
since it is not doing anything useful anyway ;-)
Thank you for all your support. By removing all code and re-assembling step by step I foundt the reason. Just in case someone runs in the same problem one day.
I had an OnScrollListener on the ListView declared in the superclass. In the OnScrollListener I was hiding the navigation Arrows on demand with Visibility.GONE. Even if the NavigationArrows did not affect the layout of the ListView this was the problem. By setting Visibility.INVISIBLE everything works fine. I guess this is related to some re-drawing-issue of the whole layout that does not work.

Android lock checkboxes when not in edit mode in custom array adapter

I have a Activity that displays a list of check boxes (Focus Areas) that can be assigned to an activity event in my application. However I want to be able to prevent the user form editing these values until a button is clicked to put the form into edit mode.
Can some one explain or provide code sample how I can implement this into my application?
This list is held in a ListView with a custom ArrayAdapter of a Type FocusArea a class I have created for my application.
The xml for the Activity is shown below:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" android:background="#drawable/horizontal_gradient_line_reverse">
<TextView
android:id="#+id/textViewCustomerNameNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="Customer Name & Number" android:layout_margin="5dp"/>
<ListView
android:id="#+id/listViewFocusAreas"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/relativeLayoutControls"
android:layout_alignParentLeft="true"
android:layout_below="#+id/textViewCustomerNameNumber"
android:layout_margin="5dp"
android:background="#drawable/myborder" >
</ListView>
<RelativeLayout
android:id="#+id/relativeLayoutControls"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true" >
<ImageView
android:id="#+id/imageViewCancelFocusAreaChanges"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:src="#drawable/ic_mini_undo" />
<ImageView
android:id="#+id/imageViewSaveFocusAreaChanges"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/imageViewCancelFocusAreaChanges"
android:src="#drawable/ic_mini_save" />
<ImageView
android:id="#+id/imageViewEditFocusArea"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/imageViewSaveFocusAreaChanges"
android:src="#drawable/ic_mini_edit" />
</RelativeLayout>
<ImageView
android:id="#+id/imageViewEditMode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/textViewCustomerNameNumber"
android:layout_alignRight="#+id/listViewFocusAreas"
android:src="#drawable/edit16x16"
android:visibility="gone" />
</RelativeLayout>
The following is the xml for the focus area row:
<?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" >
<CheckBox
android:id="#+id/checkBoxFocusArea"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Focus Area" />
</LinearLayout>
The following is the code for the Custom ArrayAdapter:
public class FocusAreaAdapter extends ArrayAdapter<FocusArea> {
private ArrayList<FocusArea> focusAreas;
private Context context;
public FocusAreaAdapter(Context context, int textViewResourceId, ArrayList<FocusArea> focusAreas) {
super(context, textViewResourceId, focusAreas);
this.context = context;
this.focusAreas = focusAreas;
}
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
View v = convertView;
if(v == null) {
LayoutInflater vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.focus_area_menu_item, null);
}
FocusArea focusArea = focusAreas.get(position);
if(focusArea != null) {
CheckBox cbFocusArea = (CheckBox)v.findViewById(R.id.checkBoxFocusArea);
cbFocusArea.setText(focusArea.getFocusAreaCodeDescription());
if(focusArea.isFocusAreaCodeChecked() == 1) {
cbFocusArea.setChecked(true);
} else {
cbFocusArea.setChecked(false);
}
cbFocusArea.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
FocusArea focusArea = focusAreas.get(position);
if(focusArea.isFocusAreaCodeChecked() == 1) {
focusArea.setFocusAreaCodeChecked(0);
} else {
focusArea.setFocusAreaCodeChecked(1);
}
}
});
}
return v;
}
}
Finally I instanciate my custom array adapter with the following code:
private void assignFocusAreasToAdapter() {
// get reference to available responsibles list view control
lvFocusAreas.clearChoices();
// create an array adapter with the communications data array
activityFocusAreaAdapter = new FocusAreaAdapter(this, R.layout.focus_area_menu_item, activityFocusAreas);
// assign the my customers list control the array adapter
lvFocusAreas.setAdapter(activityFocusAreaAdapter);
activityFocusAreaAdapter.notifyDataSetChanged();
Log.i(TAG, "Available Activity Focus Areas Loaded");
}
Ok i found the solution to this problem for anyone who might have the same issue.
The XML for the Focus Area activity stays the same as posted above.
The XML for the Focus Area row item is modified accordingly:
<?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"
android:descendantFocusability="blocksDescendants" >
<CheckBox
android:id="#+id/checkBoxFocusArea"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Focus Area" />
</LinearLayout>
You can see that this now has the following line added android:descendantFocusability="blocksDescendants" This prevents the checkboxes onClickListener from firing which normally will block the ListViews OnItemClickedListener from firing.
The Custom Adapter code is modified to remove the checkboxes OnClickListener like so:
public class FocusAreaAdapter extends ArrayAdapter<FocusArea> {
private ArrayList<FocusArea> focusAreas;
private Context context;
public FocusAreaAdapter(Context context, int textViewResourceId, ArrayList<FocusArea> focusAreas) {
super(context, textViewResourceId, focusAreas);
this.context = context;
this.focusAreas = focusAreas;
}
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
View v = convertView;
if(v == null) {
LayoutInflater vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.focus_area_menu_item, null);
}
FocusArea focusArea = focusAreas.get(position);
if(focusArea != null) {
CheckBox cbFocusArea = (CheckBox)v.findViewById(R.id.checkBoxFocusArea);
cbFocusArea.setText(focusArea.getFocusAreaCodeDescription());
if(focusArea.isFocusAreaCodeChecked() == 1) {
cbFocusArea.setChecked(true);
} else {
cbFocusArea.setChecked(false);
}
cbFocusArea.setClickable(false);
}
return v;
}
}
The Custom Adapter is instanciated using the same code as posted in above but you must add an OnItemClickListener to the ListView and preform the check of the checkbox inside the OnItemClickListener click event like so:
lvFocusAreas = (ListView)findViewById(R.id.listViewFocusAreas);
lvFocusAreas.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
if(editMode){
FocusArea focusArea = (FocusArea)lvFocusAreas.getItemAtPosition(position);
if(focusArea.isFocusAreaCodeChecked() == 0) {
focusArea.setFocusAreaCodeChecked(1);
} else {
focusArea.setFocusAreaCodeChecked(0);
}
activityFocusAreaAdapter.notifyDataSetChanged();
setControlsEnabled();
}
}
});
Hope this helps any one thats having the same problem. :D

Removing an Item with a Button in ListView with Custom ArrayAdapter

I have custom list_row :
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="wrap_content" android:baselineAligned="false">
<Button android:layout_width="30dip" android:layout_marginTop="7dip" android:gravity="right"
android:id="#+id/delete" android:layout_height="30dip" android:background="#drawable/delete"
android:layout_gravity="top"></Button>
<TextView android:textSize="20dip"
android:text="TextView" android:id="#+id/tavsiye" android:layout_marginTop="10dip"
android:layout_gravity="top" android:layout_width="wrap_content"
android:layout_height="wrap_content"></TextView>
</LinearLayout>
I have a ListView like that:
<ListView
android:id="#+id/tavsiyeler"
android:layout_height="300dip"
android:layout_width="170dip"
android:fastScrollEnabled="true"
android:scrollbars="vertical"/>
and a custom adapter which extends ArrayAdapter :
public class HekimTavsiyeleriAdapter extends ArrayAdapter<String> {
private Context context;
private int resource;
private ArrayList<String> tavsiyeler;
public HekimTavsiyeleriAdapter(Context context, int resource,
ArrayList<String> objects) {
super(context, resource, objects);
this.context=context;
this.resource=resource;
this.tavsiyeler=objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(this.resource, null);
}
if (this.tavsiyeler.size()!=0) {
TextView tavsiye = (TextView) v.findViewById(R.id.tavsiye);
Button but= (Button) v.findViewById(R.id.delete);
if (tavsiye != null) {
String st=this.tavsiyeler.get(position);
tavsiye.setText(st);
}
if( but!=null){
but.setId(position);
but.setOnClickListener(new AdapterView.OnClickListener() {
#Override
public void onClick(View v) {
int id=v.getId();
tavsiyeler.remove(id);
notifyDataSetChanged();
}
});
}
}
return v;
}
I am creating adapter and fill the list like that :
eklenecekTavsiyeler=new ArrayList<String>();
adapter= new HekimTavsiyeleriAdapter(context,
R.layout.hekim_tavsiyeleri_row, eklenecekTavsiyeler);
ListView tavsiyelerListesi = (ListView)findViewById(R.id.tavsiyeler);
tavsiyelerListesi.setAdapter(adapter);
And adding new items like that:
this.adapter.add(<some-string>);
this.adapter.notifyDataSetChanged();
and my list view is seen like that:
http://imageshack.us/photo/my-images/97/listir.jpg/
Here is my question:
I am adding new items to the list. I have fixed height for the list. When I fill the list until all height is occupied, then I add one new item to the list which requires scrolling becasue overflow in list height. The last item I added gets wrong id and when I pressed the cross button, it removes wrong item. However, when the list is not overflowed, everything works fine. After overflow, the ids of buttons are set wrongly (seems randomly). By the way, for setting the button's id, I am using getView's position argument.
Thanks in advance.
I am afraid that you have flaw in the code.
You have to stop calling but.setId(). With this you are overriding internal id of the view which is the value of R.id.delete. Probably you meant to use but.setTag() / but.getTag()?

Categories

Resources