ImageView onClick method - java

I have an activity MyActivityListView and her xml file is this http://pastebin.com/B2thprhT.
The activity does nothing to special , when we click on a row calls another activity passing elements. The rows of this xml are build using this other xml file http://pastebin.com/H321gRP8.
In the activity associated ad the first xml file on the onCreate() method its present this row: listView.setAdapter(new MyListViewAdapter(getApplicationContext())); and the MyListViewAdapter is made in this way
public class MyListViewAdapter extends BaseAdapter {
List<TestTable> testTableArrayList;
private LayoutInflater inflater;
private Context context;
private DatabaseHelper databaseHelper;
public MyListViewAdapter(/*ArrayList<TestTable> testTableArrayList,*/ Context context) {
// this.testTableArrayList = testTableArrayList;
this.context = context;
this.databaseHelper = new DatabaseHelper(context);
this.testTableArrayList = databaseHelper.getValues();
inflater = ( LayoutInflater )context.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
/**
* Ritorna il numero degli elementi presenti nell'ArrayList
* #return numero di elementi nell'ArrayList
*/
#Override
public int getCount() {
// return 0;
return testTableArrayList.size();
}
/**
* Restituisce l'oggetto in posizione position
* #param position = posizione dell'oggetto che verra' restituito
* #return oggetto in posizione position
*/
#Override
public Object getItem(int position) {
// return null;
return testTableArrayList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.custom_single_row_list_view, null);
TextView zero = (TextView) row.findViewById(R.id.txtIdOnCustomView);
TextView uno = (TextView) row.findViewById(R.id.txtPrimoValoreOnCustomView);
TextView due = (TextView) row.findViewById(R.id.txtSecondoValoreOnCustomView);
TextView tre = (TextView) row.findViewById(R.id.txtTerzoValoreOnCustomView);
TestTable temp = testTableArrayList.get(position);
zero.setText(String.valueOf(temp.getId()));
uno.setText(temp.getVal1());
due.setText(temp.getVal2());
tre.setText(temp.getVal3());
// TextView uno
return row;
}
}`
As you see, in the second xml file is present an ImageView that is clickable, but I don't understand where insert the method associated at the click because if I insert that method on MyListViewAdapter class they return an error, if I insert on ActivityListView class they return error.
Thank at all and forgive me for my english, it's the first time I ask something in english :)

Just use findViewById() to get a reference to your ImageView like you did with the TextViews and set an OnClickListener in code. Do this in the same place where you also get your TextViews.

Related

Listview show only last item over and over

I am new to android development. I enrolled Udacity course and I get to where I have to use a costume arrayAdapter to display a listView of data (text) I nailed most of it but i have a problem with data displayed which is : when I launch my activity listView displays last item on may arraylist
i have tried almost everything out their nothing worked for me
My Data
/**
* Displays text to the user.
*/
public class Numbers {
//First we Set the Stat of our Class :
// English Translation
public static String englishTranslation;
//Tamazight Translation
public static String tamazightTranslation;
/**
* Create a new Numbers Object :
*
* #param englishTranslation is for ENGLISH NUMBERS
* #param tamazightTranslation is for TAMAZIGHT NUMBERS
*/
//Constructor
public Numbers(String englishTranslation, String tamazightTranslation) {
this.englishTranslation = englishTranslation;
this.tamazightTranslation = tamazightTranslation;
}
//Getter
public static String getEnglishTranslation() {
return englishTranslation;
}
public static String getTamazightTranslation() {
return tamazightTranslation;
}
}
My ArrayList :
public class ActivityNumbers extends AppCompatActivity {
//Add English numbers to The ARRAYList
ArrayList<Numbers> englishNumbers = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_numbers);
englishNumbers.add(new Numbers("One", "Yan"));
englishNumbers.add(new Numbers("Two", "Sin"));
englishNumbers.add(new Numbers("Three", "Krad"));
englishNumbers.add(new Numbers("Four", "Koz"));
englishNumbers.add(new Numbers("Five", "Smos"));
englishNumbers.add(new Numbers("Six", "Sdis"));
englishNumbers.add(new Numbers("Seven", "Sa"));
englishNumbers.add(new Numbers("Eight", "Tam"));
englishNumbers.add(new Numbers("Nine", "Tza"));
englishNumbers.add(new Numbers("Ten", "Mraw"));
//EnglishNumbers.remove(0);
//EnglishNumbers.size();
// EnglishNumbers.get(1);
//Create a NEW TV object
/**Creating an ArrayAdapter (DATA HOLDER)
#param Context / the ACTIVITY concerned
#param Android.R.layout : an XML layout file contains TextView predefined by Android
#param Items to display */
NumbersAdapter itemsAdapter = new NumbersAdapter (this, englishNumbers);
// Linking the ListView object to a Variable
ListView numbersListView = (ListView) findViewById(R.id.list);
//Calling setAdapter Method on numbersListView with "itemsAdapter
numbersListView.setAdapter(itemsAdapter);
}
}
My Adapter :
public class NumbersAdapter extends ArrayAdapter<Numbers> {
public NumbersAdapter(Context context, ArrayList<Numbers> englishNumbers) {
super(context, 0, englishNumbers);
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View listItemView = convertView;
if (listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(R.layout.listitem, parent, false);
}
Numbers numbers = getItem(position);
System.out.println(position);
TextView tamazight_item = (TextView) listItemView.findViewById(R.id.tamazight_item);
TextView english_item = (TextView) listItemView.findViewById(R.id.english_item);
tamazight_item.setText(numbers.getEnglishTranslation());
System.out.println(numbers.getEnglishTranslation());
english_item.setText(numbers.getTamazightTranslation());
System.out.println(numbers.getTamazightTranslation());
return listItemView;
}
}
try this way
Context context;
ArrayList<Numbers> englishNumbers;
public NumbersAdapter(Context context, ArrayList<Numbers> englishNumbers)
{
this.context=context;
this.englishNumbers=englishNumbers;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
convertView= LayoutInflater.from(context).inflate(R.layout.listitem,parent,false);
TextView tamazight_item = (TextView) listItemView.findViewById(R.id.tamazight_item);
TextView english_item = (TextView) listItemView.findViewById(R.id.english_item);
tamazight_item.setText(englishNumbers.get(position).getEnglishTranslation());
english_item.setText(englishNumbers.get(position).getTamazightTranslation());
return convertView;
}
And not forgot to make NumbersAdapter extends BaseAdapter
Your tamazightTranslation and englishTranslation attributes are static on the Numbers class meaning that, those are class attributes. Remove static from the variables and from the getters and you should be fine. See the difference between class attributes and instance attributes here https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
I have changed your model class and Adapter class please follow this It will work
public class Numbers {
//First we Set the Stat of our Class :
// English Translation
private String englishTranslation;
//Tamazight Translation
private String tamazightTranslation;
public String getEnglishTranslation() {
return englishTranslation;
}
public void setEnglishTranslation(String englishTranslation) {
this.englishTranslation = englishTranslation;
}
public String getTamazightTranslation() {
return tamazightTranslation;
}
public void setTamazightTranslation(String tamazightTranslation) {
this.tamazightTranslation = tamazightTranslation;
}
}
Adapter Class
public class NumbersAdapter extends ArrayAdapter<Numbers> {
private Context mContext;
private ArrayList<Numbers>list;
public NumbersAdapter(Context context, ArrayList<Numbers> englishNumbers) {
super(context, 0, englishNumbers);
this.mContext=context;
this.list = englishNumbers;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View listItemView = convertView;
if (listItemView == null) {
listItemView = LayoutInflater.from(mContext).inflate(R.layout.listitem, parent, false);
}
Numbers numbers = list.get(position);
System.out.println(position);
TextView tamazight_item = (TextView) listItemView.findViewById(R.id.tamazight_item);
TextView english_item = (TextView) listItemView.findViewById(R.id.english_item);
tamazight_item.setText(numbers.getEnglishTranslation());
System.out.println(numbers.getEnglishTranslation());
english_item.setText(numbers.getTamazightTranslation());
System.out.println(numbers.getTamazightTranslation());
return listItemView;
}
}
If it is showing one last item in your listview, there might be several reasons for that.
You need to override getCount() in ArrayAdapter to have size of the list. It may fix the problem.
Make sure, the list view is not declared inside scrollview in your xml layout. If it is, handle it properly using nestedscrollview or else.
If it is showing the same data in all rows of your list view, then it might be
In your case, you need to remove static keywords in front of properties, static means that properties or methods belong to Number class, not to the instance of your Number class object. Basically, it must be the reason.

Android different Row layout only for first row in BaseAdapter

I am making an Custom listview with Custom Adapter extending BaseAdapter. Now I want to set a different layout only for first row and another layout for all other rows. I am using this code but it sets the special layout for 1st row and also repeats it after every 5/6 rows. How can I fix it and can set it only for 1st row and another layout for all other rows.
public class NewsAdapter extends BaseAdapter {
private Context context;
List<News> newsList;
private Typeface customBanglaFont;
private LayoutInflater inflater;
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
public NewsAdapter(Context context, List<News> newsList){
this.context = context;
this.newsList = newsList;
}
#Override
public int getCount() {
return newsList.size();
}
#Override
public Object getItem(int arg0) {
return newsList.get(arg0);
}
#Override
public long getItemId(int arg0) {
return arg0;
}
#Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
View row;
row = convertView;
ViewHolder holder=null;
if(row == null){
if(position == 0){
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row =inflater.inflate(R.layout.row_single_big_view,viewGroup,false);
}
else{
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row =inflater.inflate(R.layout.row_single_default,viewGroup,false);
}
holder = new ViewHolder(row);
row.setTag(holder);
}
else{
holder = (ViewHolder) row.getTag();
}
if (imageLoader == null){
imageLoader = AppController.getInstance().getImageLoader();
}
final News news = newsList.get(position);
customBanglaFont = Typeface.createFromAsset(viewGroup.getContext().getAssets(), "fonts/SolaimanLipi.ttf");
holder.newsTitleView.setTypeface(customBanglaFont);
holder.newsTitleView.setText(news.getTitle());
holder.thumbNail.setImageUrl(news.getFeaturedImgSrc(), imageLoader);
return row;
}
}
/**
* Custom View Holder Class
* #author Tonmoy
*
*/
class ViewHolder{
TextView newsTitleView;
NetworkImageView thumbNail;
public ViewHolder(View v) {
// TODO Auto-generated constructor stub
newsTitleView = (TextView) v.findViewById(R.id.news_title);
thumbNail = (NetworkImageView) v.findViewById(R.id.news_image);
}
}
Why don't you use the Header functionality already built into ListView for this specific thing.
The docs:
http://developer.android.com/reference/android/widget/ListView.html#addHeaderView%28android.view.View,%20java.lang.Object,%20boolean%29
or a SO question:
Using ListView : How to add a header view?
your attempting is wrong. Your way you will be able to inflate just one layout. In fact, after the method returns the first time, convertView is not null. To fix quickly you could override getViewTypeCount and getItemViewType. This way you will get convertViews eqaul to the return value of getViewTypeCount, or you could just add the first item as header view for the ListView

Android Listview clickable textview

I have made an Listview populated with list_row_layout.xml(which is populated with json serializable class), i have clickable textview and onclick changing text from "Accept" to "Accepted". But when i click it on first listview item, another textview listview items below are changing.
Here's some photos to descibe you better
this is the adapter class
public class CustomListAdapter extends BaseAdapter {
private ArrayList<FeedItem> listData;
private LayoutInflater layoutInflater;
private Context mContext;
public CustomListAdapter(Context context, ArrayList<FeedItem> listData) {
this.listData = listData;
layoutInflater = LayoutInflater.from(context);
mContext = context;
}
#Override
public int getCount() {
return listData.size();
}
#Override
public Object getItem(int position) {
return listData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.list_row_layout, null);
holder = new ViewHolder();
holder.headlineView = (TextView)convertView.findViewById(R.id.sex);
holder.reportedDateView = (TextView) convertView.findViewById(R.id.confid);
holder.approve = (TextView) convertView.findViewById(R.id.approveTV);
holder.approve.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View argView)
{
holder.approve.setText("Accepted");
}
}
);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
FeedItem newsItem = (FeedItem) listData.get(position);
holder.headlineView.setText(Html.fromHtml(newsItem.getTitle()));
holder.reportedDateView.setText(Html.fromHtml(newsItem.getContent()));
return convertView;
}
static class ViewHolder {
TextView approve;
TextView headlineView;
TextView reportedDateView;
ImageView imageView;
}
}
Remember that views can be recycled via convertView.
In your onClick method you set the approve text to "Accepted" but when the view is recycled, you never set it back to "Accept"
Actually you need to update (something in) the list in response to an click and have the Accept/Accepted value toggle based on that value rather than simply updating what is currently visible on the screen.
-- to answer the "how" question (asked below)--
Add a new field to ViewHolder
static class ViewHolder {
TextView approve;
TextView headlineView;
TextView reportedDateView;
ImageView imageView;
FeedItem newsItem;
}
Change the onClick method:
public void onClick(View argView)
{
// note that holder no longer needs to be final in the parent class
// because it is not used here.
View parent = (View)argView.getParent();
ViewHolder clickedHolder = (ViewHolder)parent.getTag();
clickedHolder .newsItem.setAccepted(true); /// a new method
clickedHolder .approve.setText ("Accepted");
Log.d(TAG, "Accepted item #" + position);
}
After you have convertView created (if necessary)
FeedItem newsItem = (FeedItem) listData.get(position);
holder.newsItem = newsItem; // populate the new field.
holder.headlineView.setText(Html.fromHtml(newsItem.getTitle()));
holder.reportedDateView.setText(Html.fromHtml(newsItem.getContent()));
if(newsItem.isAccepted ()){ // another new method!
holder.approve.setText ("Accepted");
Log.d(TAG, "Set text to Accepted for item #" + position);
}else{
holder.approve.setText("Accept");
Log.d(TAG, "Set text to Accept for item #" + position);
}
Once it is working you should consider removing the Log.d() lines to cut down on the noise in LogCat.

Delete item from listview

I have listview which contains textview and buttons. When i delete listview item and i try to scroll down, i get exception on this:
BuildQueue eile = countryList.get(position);
Exception:
02-08 19:11:04.279: E/AndroidRuntime(10509): java.lang.IndexOutOfBoundsException: Invalid index 15, size is 15
Seems i do not updating something when i delete item from listview. I think i have problem with ViewHolder, but i do not know what kind of...
My ArrayAdapter code:
public class MyCustomAdapter extends ArrayAdapter<BuildQueue> {
private ArrayList<BuildQueue> countryList;
public MyCustomAdapter(Context context, int textViewResourceId,ArrayList<BuildQueue> countryList) {
super(context, textViewResourceId, countryList);
this.countryList = new ArrayList<BuildQueue>();
this.countryList.addAll(countryList);
}
private class ViewHolder {
TextView code;
TextView field;
Button del;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.queue_buildings, null);
holder = new ViewHolder();
holder.code = (TextView) convertView.findViewById(R.id.code);
holder.field = (TextView) convertView.findViewById(R.id.field_text);
holder.del = (Button) convertView.findViewById(R.id.del_button);
convertView.setTag(holder);
holder.del.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Button del_button = (Button) v;
BuildQueue building = (BuildQueue) del_button.getTag();
countryList.remove(building);
dataAdapter.notifyDataSetChanged();
}
});
} else {
holder = (ViewHolder) convertView.getTag();
}
BuildQueue eile = countryList.get(position);
holder.code.setText(" ( Level: " + eile.getOld_level() + " to "+eile.getNew_level()+")");
holder.field.setText(eile.getNameSort());
holder.field.setTag(eile);
holder.del.setText("Delete");
holder.del.setTag(eile);
return convertView;
}
}
You are using a two arrays in your Adapter, but only changing one of them.
Every Adapter uses getCount() to determine how many row should be drawn. ArrayAdapter's getCount() simply asks for the size of the array that you pass to the super constructor here: super(context, textViewResourceId, countryList);. But you are also using a second, local array and when you delete a value from this countryList getCount() has no idea this happened which results in getView() throwing an IndexOutOfBoundsException...
Either extend BaseAdapter, or use ArrrayAdapter's methods like getItem(), add(), and remove() and remove your local data set.

Android Listview Caching work unexpectedly on initialization

I have a bit troublesome with view caching in listview (a.k.a convertView)
so here is my code,
private class CurrencyAdapter extends ArrayAdapter<CurrencyModel> {
Context ctx;
int layoutResourceId;
List<CurrencyModel> adapter_models = null;
public CurrencyAdapter(Context ctx, int layoutResourceId,
List<CurrencyModel> model) {
super(ctx, layoutResourceId, model);
this.ctx = ctx;
this.layoutResourceId = layoutResourceId;
adapter_models = model;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
Log.d(Constants.APP_TAG, "position: " + position);
View row = convertView;
CurrencyAdapterContainer holder = null;
if (row == null) {
Log.d(Constants.APP_TAG, "APP NULL");
row = ((Activity) ctx).getLayoutInflater().inflate(
layoutResourceId, parent, false);
holder = new CurrencyAdapterContainer();
holder.textView = (TextView) row
.findViewById(R.id.currencies_txt);
holder.imgView = (ImageView) row
.findViewById(R.id.currencies_flag_icon);
row.setTag(holder);
} else {
Log.d(Constants.APP_TAG, "APP NOT NULL");
holder = (CurrencyAdapterContainer) row.getTag();
}
CurrencyModel curr = getItem(position);
if (curr.currency_value == null) {
if (counter < MAX_COUNTER) {
++counter;
CurrencyJsonDownloader cDownloader = new CurrencyJsonDownloader(
curr, holder.textView); //download currency value in background, and set textview text if currency_value has been loaded in onpostExcecute (i'm using AsyncTask)
String url = CURRENCY_URL.replace("<symbol>", curr.symbol);
Log.d(Constants.APP_TAG, "Url currency: " + url);
cDownloader.execute(url);
}
holder.textView.setText("");
} else {
holder.textView.setText(curr.currency_value);
}
holder.imgView.setImageResource(curr.drawableId);
return row;
}
#Override
public CurrencyModel getItem(int position) {
// TODO Auto-generated method stub
return adapter_models.get(position);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return adapter_models.size();
}
}
static class CurrencyAdapterContainer {
ImageView imgView;
TextView textView;
}
and here is the output in my logcat
position : 0
APP NULL
position : 1
APP NOT NULL
position : 2
APP NOT NULL
position : 3
APP NOT NULL
.
.
.
position : 10
APP NOT NULL
which make a disaster because it means that the textview being passed in the background job is the same textview and the the changed view is the same textview and the other textview will have blank view unless i scroll it of course which call again the getView() and everything is fine. But it's a problem when starting the app, because just one textview that always changing its value.
so why is this happen? and is there any hack that i can do??
thanks before...
ListView item Views are recycled, so never hold a reference to a particular item view and expect it to represent same data after ListView has been scrolled.
Pass the data item to your worker task instead and let it update the data to it.
Updating:
If your current item is off screen, It'll be requested from adapter (
when ListView scroll to it), and will show updated data.
If that item is currently being displayed , call notifyDataSetChanged() on adapter, this will make ListView refresh its displayed items.
I think problem is with your List adapter. Here i had posted a adapter class i think it will help you.
public class UploadListAdaptor extends BaseAdapter {
private Context context;
private List<UploadDetailsObj> uploadList;
public UploadListAdaptor(Context context, List<UploadDetailsObj> list) {
this.context = context;
uploadList = list;
}
public int getCount() {
return uploadList.size();
}
public Object getItem(int position) {
return uploadList.get(position);
}
public long getItemId(int position) {
return position;
}
/** LIST CATEGORY */
public View getView(int position, View convertView, ViewGroup viewGroup) {
final UploadDetailsObj chlListObj = uploadList.get(position);
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater
.inflate(R.layout.inflator_progress_bar, null);
TextView photoName = (TextView) convertView
.findViewById(R.id.tv_photoname);
Button btnProgress=(Button)convertView.findViewById(R.id.btn_progress);
photoName.setText(chlListObj.getPhotoName());
}
return convertView;
}
}
You can call this adapter by using this code.
List<UploadDetailsObj> listofUploads= new ArrayList<UploadDetailsObj>();
UploadListAdaptor uploadListAdptr = new UploadListAdaptor(yourclass.this,
listofUploads);
uploadListView.setAdapter(uploadListAdptr);

Categories