I work in an app in which I want to display in top the month and a left/right arrow for the previous/next months. So far so good.
Down of the month, I want to display a List of names. This is for now. My app is in the first stages.
Looks easy but the list doesn't appear and I can't figure out why.
Here is a preview of the screen.
Here is all the classes and layouts I use.
MainActivity.java
package team.proodeutikiekriksitoumpas;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class MainActivity extends Activity {
public GregorianCalendar month, itemmonth;// calendar instances.
ListView NamesListView, DataListView;
ArrayList<String> NamesFeedList, DataFeedList;
MyNamesAdapter NamesAdapter;
//, DataAdapter;
//public CalendarAdapter adapter;// adapter instance
public Handler handler;// for grabbing some event values for showing the dot marker.
//public ArrayList<String> items; // container to store calendar items which needs showing the event marker
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//DataListView = (ListView) findViewById(R.id.DataListView);
NamesFeedList = new ArrayList<String>();
NamesFeedList.add("Kostis A");
NamesFeedList.add("Apostolis B");
NamesAdapter = new MyNamesAdapter(this, R.layout.name_item_view, R.id.name, NamesFeedList);
NamesListView = (ListView) findViewById(R.id.NamesListView);
NamesListView.setAdapter(NamesAdapter);
/*
DataFeedList = new ArrayList<String>();
DataFeedList.add("Ok");
DataFeedList.add("Ok");
DataAdapter = new ArrayAdapter<String>(this, R.layout.data_item_view, R.id.data, DataFeedList);
DataListView.setAdapter(DataAdapter);
*/
month = (GregorianCalendar) GregorianCalendar.getInstance();
itemmonth = (GregorianCalendar) month.clone();
//Sitems = new ArrayList<String>();
//adapter = new CalendarAdapter(this, month);
handler = new Handler();
//handler.post(calendarUpdater);
TextView title = (TextView) findViewById(R.id.title);
title.setText(android.text.format.DateFormat.format("MMMM yyyy", month));
RelativeLayout previous = (RelativeLayout) findViewById(R.id.previous);
previous.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
setPreviousMonth();
refreshCalendar();
}
});
RelativeLayout next = (RelativeLayout) findViewById(R.id.next);
next.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
setNextMonth();
refreshCalendar();
}
});
}
protected void setNextMonth() {
if (month.get(GregorianCalendar.MONTH) == month
.getActualMaximum(GregorianCalendar.MONTH)) {
month.set((month.get(GregorianCalendar.YEAR) + 1),
month.getActualMinimum(GregorianCalendar.MONTH), 1);
} else {
month.set(GregorianCalendar.MONTH,
month.get(GregorianCalendar.MONTH) + 1);
}
}
protected void setPreviousMonth() {
if (month.get(GregorianCalendar.MONTH) == month
.getActualMinimum(GregorianCalendar.MONTH)) {
month.set((month.get(GregorianCalendar.YEAR) - 1),
month.getActualMaximum(GregorianCalendar.MONTH), 1);
} else {
month.set(GregorianCalendar.MONTH,
month.get(GregorianCalendar.MONTH) - 1);
}
}
public void refreshCalendar() {
TextView title = (TextView) findViewById(R.id.title);
//adapter.refreshDays();
//adapter.notifyDataSetChanged();
//handler.post(calendarUpdater); // generate some calendar items
title.setText(android.text.format.DateFormat.format("MMMM yyyy", month));
}
/**
* public Runnable calendarUpdater = new Runnable() {
#Override
public void run() {
items.clear();
// Print dates of the current week
DateFormat df = new SimpleDateFormat("yyyy-MM-dd",Locale.US);
String itemvalue;
for (int i = 0; i < 7; i++) {
itemvalue = df.format(itemmonth.getTime());
itemmonth.add(GregorianCalendar.DATE, 1);
items.add("2012-09-12");
items.add("2012-10-07");
items.add("2012-10-15");
items.add("2012-10-20");
items.add("2012-11-30");
items.add("2012-11-28");
}
//adapter.setItems(items);
//adapter.notifyDataSetChanged();
}
};
**/
}
MyNamesAdapter.java
package team.proodeutikiekriksitoumpas;
import java.util.ArrayList;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class MyNamesAdapter extends ArrayAdapter<String> {
// declaring our ArrayList of Strings
private ArrayList<String> objects;
public MyNamesAdapter(Context context, int resource, int textViewResourceId, ArrayList<String> objects) {
super(context, resource, textViewResourceId, objects);
this.objects = objects;
Log.v(null, "listaaaaaaaaa");
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
//return super.getView(position, convertView, parent);
// assign the view we are converting to a local variable
View v = convertView;
// first check to see if the view is null. if so, we have to inflate it.
// to inflate it basically means to render, or show, the view.
if (v == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.name_item_view, null);
}
/*
* Recall that the variable position is sent in as an argument to this method.
* The variable simply refers to the position of the current object in the list.
* (The ArrayAdapter iterates through the list we sent it)
*
* Therefore, s refers to the current String object.
*/
String s = null;
if(objects != null) {
s = objects.get(position);
Log.v(null, s);
}
else{
Log.v(null, "null objects");
}
if (s != null) {
Log.v(null, "to textviews");
// This is how you obtain a reference to the TextViews.
// These TextViews are created in the XML files we defined.
TextView name = (TextView) v.findViewById(R.id.name);
// check to see if each individual textview is null.
// if not, assign some text!
if (name != null){
name.setText(s);
}
}
return v;
}
}
activity_main.xmml
<?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="horizontal" >
<RelativeLayout
android:id="#+id/header"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="#+id/previous"
android:layout_width="40dip"
android:layout_height="30dip"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true" >
<ImageView
android:contentDescription="#string/desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="#drawable/arrow_left" />
</RelativeLayout>
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="5dip"
android:textColor="#000000"
android:text="November"
android:textSize="18sp"
android:textStyle="bold" />
<RelativeLayout
android:id="#+id/next"
android:layout_width="40dip"
android:layout_height="30dip"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true" >
<ImageView
android:contentDescription="#string/desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="#drawable/arrow_right" />
</RelativeLayout>
</RelativeLayout>
<ListView
android:id="#+id/NamesListView"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
name_item_view.xml
<?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="horizontal"
tools:context=".MainActivity" >
<TextView
android:id="#+id/name"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text=""
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
Thanks in advance.
there are multiple things here:
activity_main.xml
change android:orientation="horizontal" to "vertical". As you said before, you want the list to be displayed below.
name_item_view.xml
both the layout and the textfield are matching the height. this can be problematic. try having "wrap content" for the text here. also it is not clear on why you actually need a linearlayout wrapped for the textview. maybe try with a simpler version just using the textview. if you want things to be sized, you need something that tells the size. if your list doesnt, then the elements have to. you could have a minimum_height, but it really needs something there to work correctly.
in general you should avoid having listviews using custom length. depending on what exactly you are trying to do it might be perfectly fine to just add those views to a linearlayout if its not that many anyway. otherwise you will have problems very soon. listview is designed to be a size and scrollable - not to be in a scrollcontainer. even though you can make this work, it should be considered a hack.
note: in recyclerview this will not be possible anymore
it might therefore be a good idea to adjust your layout here to accomodate this.
means here:
use all available rest of space for the listview.
now if you like the header to scroll out you have 2 options:
make it a header and use whatever way to make this possible you can find (there are libs, do it yourself, etc)
make it a toolbar and you can just use the appcompat libs simply to make this toolbar go away when people are scrolling. this might currently be the better solution.
hope it helps
Change android:layout_height of ListView from "wrap_content" to some particular value in your xml code
Related
I created a listview with a custom adapter that allows me to have a list of items with checkboxes next to each item.
So I would like to look at the checkbox for the corresponding item in the list and see if it is checked and if it is, then set the value of boolean whiskey = false to true and so on for the other booleans.
It is very possible I have code in the wrong class or xml file, I've been trying to piece together things I've found on the internet. I'm new to android studio so its proving very difficult. I do have about a years worth of java experience though. I have all my code written in a working program on Eclipse, I am just having a hell of a time figuring out how to implement it into a working app.
Thanks in advance.
customAdapter.java
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import java.util.ArrayList;
public class customAdapter extends BaseAdapter {
private ArrayList<String> list = new ArrayList<String>();
private Context context;
public customAdapter(ArrayList<String> list, Context context) {
this.list = list;
this.context = context;
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int pos) {
return list.get(pos);
}
public void setChecked(boolean isChecked){
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.activity2_listview, null);
}
//Handle TextView and display string from your list
TextView label = (TextView)view.findViewById(R.id.label);
label.setText(list.get(position));
//Handle buttons and add onClickListeners
CheckBox callchkbox = (CheckBox) view.findViewById(R.id.cb);
callchkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//update isChecked value to model class of list at current position
list.get(position).setChecked(isChecked);
}
});
return view;
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
Main2Activity.java
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.Arrays;
import android.widget.CheckBox;
public class Main2Activity extends AppCompatActivity {
boolean Whiskey, Bourbon, Rum, Gin, Vodka, Tequila = false;
String [] userIngredients = {"Whiskey", "Bourbon", "Rum", "Gin", "Vodka", "Tequila", "Club Soda", "Lemon-Lime Soda",
"Ginger ale", "Cola", "Still mineral water", "Tonic Water", "Orange Juice", "Cranberry Juice", "Grapefruit Juice",
"Tomato Juice", "Cream or Half and Half", "Milk", "Ginger Beer", "PineApple Juice", "Lemons", "Limes", "Oranges"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
ListView listView = (ListView) findViewById(R.id.userIngredients);
ArrayList<String> list = new ArrayList<String>(Arrays.asList(userIngredients));
listView.setAdapter(new customAdapter(list, Main2Activity.this));
}
}
activity_main2.xml
<?xml version="1.0" encoding="utf-8"?>
<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=".Main2Activity"
android:id="#+id/linearLayout">
<ListView
android:layout_width="419dp"
android:layout_height="558dp"
android:id="#+id/userIngredients"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView2"
tools:layout_conversion_absoluteHeight="731dp"
tools:layout_conversion_absoluteWidth="411dp" />
<TextView
android:id="#+id/textView2"
android:layout_width="374dp"
android:layout_height="60dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:text="Check Your Ingredients"
android:textSize="24sp"
app:fontFamily="#font/cinzel"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
activity2_listview.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">
<TextView
android:id="#+id/label"
android:layout_width="323dp"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text="ingredient"
android:textSize="20sp" />
<CheckBox
android:id="#+id/cb"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
i think you can do it with a BaseAdapter as well, but i suggest to use a RecyclerView instead.
I used support-v4 and recyclerview-v7 libs as following:
(Make sure that you are not developing AndroidX - check your gradle.properties of the entire project. It is very similar but uses other libraries though.)
build.gradle
android {
compileSdkVersion 28
buildToolsVersion '28.0.3'
...
dependencies {
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:support-v4:28.0.0'
implementation 'com.android.support:design:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.android.support:recyclerview-v7:28.0.0'
...
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.widget.RelativeLayout
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">
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Check Your Ingredients"
android:textAlignment="center" />
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_chooser"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" >
</android.support.v7.widget.RecyclerView>
</android.widget.RelativeLayout>
In the activity2_listview you might want to do more design to the xml. It looks very basic now.
activity2_listview.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="wrap_content">
<TextView
android:id="#+id/listviewtextlabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text="ingredient"
android:textSize="20sp" />
<CheckBox
android:id="#+id/listviewcheckbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
In the main class we implement a callback-listener for our custom onItemAction function. We pass the listener with adapter.setActionListener(this); and add the adapter to the RecyclerViewer.
MainActivity.java
public class MainActivity extends AppCompatActivity implements CustomAdapter.ItemActionListener {
boolean Whiskey, Bourbon, Rum, Gin, Vodka, Tequila = false;
String [] userIngredients = {"Whiskey", "Bourbon", "Rum", "Gin", "Vodka", "Tequila", "Club Soda", "Lemon-Lime Soda",
"Ginger ale", "Cola", "Still mineral water", "Tonic Water", "Orange Juice", "Cranberry Juice", "Grapefruit Juice",
"Tomato Juice", "Cream or Half and Half", "Milk", "Ginger Beer", "PineApple Juice", "Lemons", "Limes", "Oranges"};
CustomAdapter adapter;
RecyclerView.LayoutManager layoutManager;
RecyclerView recyclerListView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
recyclerListView = (RecyclerView) findViewById(R.id.recycler_chooser);
ArrayList<String> list = new ArrayList<>();
list.addAll(Arrays.asList(userIngredients));
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
recyclerListView.setHasFixedSize(false);
layoutManager = new LinearLayoutManager(this);
recyclerListView.setLayoutManager(layoutManager);
System.out.println("list.size() " + list.size());
adapter = new CustomAdapter(list,MainActivity.this);
adapter.setActionListener(this);
recyclerListView.setAdapter(adapter);
} catch (Exception e){
e.printStackTrace();
}
}
// callback listener for your items
#Override
public void onItemAction(View view, CustomAdapter.CustomActions customAction, int position) {
final String itemName = adapter.getItem(position);
System.out.println(customAction + ": You clicked " + itemName + " on row number " + position);
switch(itemName){
case "Whiskey":
if(customAction== CustomAdapter.CustomActions.CHECK){
Whiskey=true;
}
else{
Whiskey=false;
}
System.out.println("Whiskey set to: " + Whiskey);
break;
case "Bourbon":
if(customAction== CustomAdapter.CustomActions.CHECK){
Bourbon=true;
}
else{
Bourbon=false;
}
System.out.println("Bourbon set to: " + Bourbon);
break;
//case xyz
// and so on
default:
System.out.println("Not programmed yet: " + itemName);
}
}
}
As said above i removed the BaseAdapter and replaced it with the RecyclerView. We had to implement a custom ViewHolder-class that contains each row in our RecyclerViewList. Within the ViewHolder we can call the method on our listener whenever a checkbox-change event occurs.
CustomAdapter.java
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import java.util.ArrayList;
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.CustomViewHolder> {
//------ helper class for the viewholder
enum CustomActions{
CHECK,UNCHECK
}
// Provide a reference to the views for each row
public class CustomViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView mTextView;
public CheckBox mCheckBox;
public CustomViewHolder(View v) {
super(v);
// the view element v is the whole linear layout element
CheckBox.OnCheckedChangeListener checkboxListenerForOneEntry = new CheckBox.OnCheckedChangeListener(){
#Override
public void onCheckedChanged(CompoundButton view, boolean isChecked) {
if (mItemActionListener != null) {
if(isChecked){
// this compoundbutton view element will be the checkbox
mItemActionListener.onItemAction(view, CustomActions.CHECK, getAdapterPosition());
}else{
mItemActionListener.onItemAction(view, CustomActions.UNCHECK, getAdapterPosition());
}
}
}
};
mTextView = v.findViewById(R.id.listviewtextlabel);
mCheckBox = v.findViewById(R.id.listviewcheckbox);
mCheckBox.setOnCheckedChangeListener(checkboxListenerForOneEntry);
}
}
//------
private ArrayList<String> list;
private Context context;
private LayoutInflater mInflater;
private ItemActionListener mItemActionListener;
public CustomAdapter(ArrayList<String> list, Context context) {
this.list = list;
this.context = context;
this.mInflater = LayoutInflater.from(this.context);
}
// allows clicks events to be caught
void setActionListener(ItemActionListener itemActionListener) {
this.mItemActionListener = itemActionListener;
}
// parent activity will implement this method to respond to click events
public interface ItemActionListener {
void onItemAction(View view, CustomActions customAction, int position);
}
// Create new views (invoked by the layout manager)
#Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = mInflater.inflate(R.layout.activity2_listview, parent, false);
return new CustomViewHolder(v);
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(CustomViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.mTextView.setText(list.get(position));
}
#Override // Return the size of your dataset (invoked by the layout manager)
public int getItemCount() {
return getCount();
}
public int getCount() {
return list.size();
}
public String getItem(int pos) {
return list.get(pos);
}
}
Feel free to use the code as you like.
For more info about the RecyclerView see the google docs: https://developer.android.com/guide/topics/ui/layout/recyclerview
I have a Gridview where I set some items from an array of string.
The code works fine, but I have a problem with it.
Everytime I add items, it "add" 10 of them and instead of jumping to the item 11, it go back to the first one. So the final result is something like:
1. 1
2. 2
3. 3
4. 4
5. 5
6. 6
7. 7
8. 8
9. 9
10. 10
11. 1
12. 2
...
As I've seen, when I navigate up/down it restart loading the data from the beggining.
Could somebody help me please? I don't know where the problem can be.
CustomGridViewActivity.java:
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
public class CustomGridViewActivity extends BaseAdapter {
private Context mContext;
private final String[] gridViewString;
private final String[] gridViewImageId;
public CustomGridViewActivity(Context context, String[] gridViewString, String[] gridViewImageId) {
mContext = context;
this.gridViewImageId = gridViewImageId;
this.gridViewString = gridViewString;
}
#Override
public int getCount() {
return gridViewString.length;
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int i, View convertView, ViewGroup parent) {
View gridViewAndroid;
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
gridViewAndroid = new View(mContext);
gridViewAndroid = inflater.inflate(R.layout.gridview_layout, null);
TextView textViewAndroid = (TextView) gridViewAndroid.findViewById(R.id.android_gridview_text);
ImageView imageViewAndroid = (ImageView) gridViewAndroid.findViewById(R.id.android_gridview_image);
textViewAndroid.setText(gridViewString[i]);
Picasso
.with(mContext)
.load(gridViewImageId[i])
.fit() // will explain later
.into((ImageView) imageViewAndroid);
//imageViewAndroid.setImageResource(gridViewImageId[i]);
} else {
gridViewAndroid = (View) convertView;
}
return gridViewAndroid;
}
}
gridview_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/android_custom_gridview_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:id="#+id/android_gridview_image"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginTop="15dp" />
<TextView
android:id="#+id/android_gridview_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:textSize="12sp" />
</LinearLayout>
content_main.xml:
<GridView
android:id="#+id/grid_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnWidth="90dp"
android:gravity="center"
android:numColumns="auto_fit"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true" />
Common.java:
//SearchPanel
static String[] gridViewString = new String[30];
static String[] gridViewImages = new String[30];
MainActivity.java:
public void Search() {
//GridView
CustomGridViewActivity adapterViewAndroid = new CustomGridViewActivity(MainActivity.this, Common.gridViewString, Common.gridViewImages);
androidGridView=(GridView)findViewById(R.id.grid_view);
androidGridView.setAdapter(adapterViewAndroid);
androidGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int i, long id) {
Toast.makeText(MainActivity.this, "GridView Item: " + Common.gridViewString[+i], Toast.LENGTH_LONG).show();
}
});
}
(JUST IN CASE, the data from the "Common" file is added by JSON and it's all different)
In your adapter's getView() method move the lines where you set the text and setup Picasso outside of the if-else block:
if (convertView == null) {
...
} else {
...
}
textViewAndroid.setText(gridViewString[i]);
Picasso
.with(mContext)
.load(gridViewImageId[i])
.fit() // will explain later
.into((ImageView) imageViewAndroid);
return gridViewAndroid;
Right now you're setting the text and image only when the row is being freshly built(convertView being null). As that row view will be recycled(used) for other rows as well, you end up with the old information as you aren't setting up the previously constructed row with new data.
I want to create a list where the listview will display a textview and an icon for each row. The diagram should be as follows:
Other than that, The data is retrieved from the database. The attribute of "favorite" will be checked first and if true, then the image in listview will be assigned with favorite_icon.png. Else, no icon need to be assigned.
I have been search for the related answer and tutorial, but all of them is too different from what I want and I cannot understand it very much. Hope somebody here can help me. Thank you in advance.
Here is what I got after I have done my Homework
First we set up a custom layout for listview and also for the row of the listview we will use later.
Here is the custom_listview_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/customListView" />
</LinearLayout>
Here is the custom_listview_row.xml
<?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:gravity="center_vertical"
android:minHeight="64dp">
<ImageView
android:id="#+id/clv_imageView"
android:layout_width="32dp"
android:layout_height="32dp"
android:contentDescription="#string/empty"
android:layout_alignParentRight="true"
android:layout_marginLeft="9dp"
android:layout_alignParentTop="true"/>
<TextView
android:id="#+id/clv_textView"
android:layout_width="97dp"
android:layout_height="32dp"
android:layout_alignParentLeft="true"
android:gravity="center_vertical"
android:text="#string/tv_definition"
android:textIsSelectable="true" />
</RelativeLayout>
Then we need to customized how our Custom ArrayAdaptor will look and do.
But before that, make sure you have put your icon in the drawable folder.
Here is my MyPerformanceArrayAdapter.java
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class MyPerformanceArrayAdapter extends ArrayAdapter<DefinitionObject>{
private List<DefinitionObject> entries;
private Activity activity;
public MyPerformanceArrayAdapter(Activity a, int textViewResourceId, List<DefinitionObject> entries) {
super(a, textViewResourceId, entries);
this.entries = entries;
this.activity = a;
}
public static class ViewHolder{
public TextView item1;
public ImageView item2;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
ViewHolder holder;
if (v == null) {
LayoutInflater vi =
(LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.custom_listview_row, null);
holder = new ViewHolder();
holder.item1 = (TextView) v.findViewById(R.id.clv_textView);
holder.item2 = (ImageView) v.findViewById(R.id.clv_imageView);
v.setTag(holder);
}
else
holder=(ViewHolder)v.getTag();
final DefinitionObject custom = entries.get(position);
if (custom != null) {
holder.item1.setText(custom.getWord());
if(custom.getFav().equalsIgnoreCase("0"))
{
holder.item2.setImageResource(R.drawable.fav);
holder.item2.setVisibility(holder.item2.INVISIBLE);
}
else
{
holder.item2.setImageResource(R.drawable.fav2);
}
}
return v;
}
}
And lastly, here is my Activity to View the ListView using the CustomArrayAdaptor.
import java.util.List;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.ListView;
public class TempCLV extends Activity {
private MySQLiteDefinitionHelper db;
String tblName = "";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom_listview_main);
Intent msjIntent = getIntent();
tblName = msjIntent.getStringExtra(WordDefinitionHomeActivity.TABLENAME2);
refresh();
}
public void refresh()
{
db = new MySQLiteDefinitionHelper(this);
final List<DefinitionObject> values = db.getAllWords(tblName);
ListView mylist = (ListView)findViewById(R.id.customListView);
MyPerformanceArrayAdapter adapter = new MyPerformanceArrayAdapter(this, R.id.customListView, values);
mylist.setAdapter(adapter);
}
}
I am setting a listView dynamically. I will have two things shown on each line that I will be receiving from parse.com. I want the first thing to be left aligned and blue, with the second thing right aligned and red. I will have two arrays, firstArray, and secondArray. I found lots of ways to do this, but none dynamically. How should I go about doing this, or I can do it in xml?
Updated
This is my xml after that tutorial posted by #t0s
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:padding="2dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="#+id/column1"
android:layout_width="50dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="#0000FF"
android:gravity="left"
/>
<TextView
android:id="#+id/center"
android:text="VS"
android:textSize="15sp"
android:layout_width="50dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="#FFFFFF"
android:gravity="center"
/>
<TextView
android:id="#+id/column2"
android:layout_width="50dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="#FF0000"
android:gravity="right"
/>
</LinearLayout>
and my java
ListView list = (ListView) findViewById(R.id.mylist);
ArrayAdapter<String> listAdapter = new ArrayAdapter<String>(MainActivity.this, R.layout.mylist, namesArray);
list.setAdapter(listAdapter);
//find my objects off parse, and call this method
private String display(Object name, Object record,
ArrayAdapter listAdapter) {
String fightCard = (name).toString();
namesArray.add((name).toString() +" " + (record).toString());
return fightCard;
}
Well my code is a mess.
Check the tutorial here is [very simple]
Ok Chad check here the code :
Main Activity :
package org.example.chad;
import java.util.ArrayList;
import android.app.ListActivity;
import android.os.Bundle;
public class MainActivity extends ListActivity {
private ArrayList<DataItem> data = new ArrayList<DataItem>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//create Objects
DataItem obj1 = new DataItem("name1", "record1");
DataItem obj2 = new DataItem("name2", "record2");
DataItem obj3 = new DataItem("name3", "record3");
DataItem obj4 = new DataItem("name4", "record4");
DataItem obj5 = new DataItem("name5", "record5");
//add the to ArrayList
data.add(obj1);
data.add(obj2);
data.add(obj3);
data.add(obj4);
data.add(obj5);
CustomAdapter adapter = new CustomAdapter(this, R.layout.row, data);
setListAdapter(adapter);
}
}
main.xml :
<RelativeLayout 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"
tools:context=".MainActivity" >
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
DataItem :
package org.example.chad;
public class DataItem {
private String name;
private String record;
public DataItem(){
}
public DataItem(String n, String r ){
this.name = n;
this.record = r;
}
public String getname() {
return name;
}
public void setname(String name) {
this.name = name;
}
public String getrecord() {
return record;
}
public void setrecord(String record) {
this.record = record;
}
}
CustomAdapter :
package org.example.chad;
import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class CustomAdapter extends ArrayAdapter<DataItem> {
private ArrayList<DataItem> objects;
public CustomAdapter(Context context, int textViewResourceId, ArrayList<DataItem> objects) {
super(context, textViewResourceId, objects);
this.objects = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.row, null);
}
DataItem i = objects.get(position);
if (i != null) {
TextView nameView = (TextView) v.findViewById(R.id.name);
TextView recordView = (TextView) v.findViewById(R.id.record);
if (nameView != null){
nameView.setText(i.getname());
}
if (recordView != null){
recordView.setText(i.getrecord());
}
}
return v;
}
}
and row.xml :
<?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="horizontal" >
<TextView
android:id="#+id/name"
android:layout_width="100sp"
android:layout_height="20sp"
android:textSize="16sp"
android:layout_gravity="left|center_vertical"
android:layout_marginLeft="10sp"/>
<TextView
android:id="#+id/record"
android:layout_width="100sp"
android:layout_height="wrap_content"
android:layout_marginLeft="10sp"
android:layout_gravity="right"
android:textSize="16sp" />
</LinearLayout>
In a couple of hours I will add some comments.
The result is here
If im not mistaken you have to extend BaseAdapter class so you have a custom Adapter for your ListView, it is not possible to add two array items to a ListView without creating a custom adapter.
here is a tutorial.
is not as hard as it looks like. Hope it helps.
Hi want to create a custom cursor adapter so I can display an image with 2 lines of text.
I have had some trouble understanding the custom cursor adapters but I do not understand how to add an imageview to be filled from the path in my database.
Will,
I've actually implemented something incredibly similar to what you are looking for. Here is my implementation.
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.Cursor;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class ItemAdapter extends CursorAdapter {
private LayoutInflater mLayoutInflater;
private Context mContext;
public ItemAdapter(Context context, Cursor c) {
super(context, c);
mContext = context;
mLayoutInflater = LayoutInflater.from(context);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View v = mLayoutInflater.inflate(R.layout.items_row, parent, false);
return v;
}
/**
* #author will
*
* #param v
* The view in which the elements we set up here will be displayed.
*
* #param context
* The running context where this ListView adapter will be active.
*
* #param c
* The Cursor containing the query results we will display.
*/
#Override
public void bindView(View v, Context context, Cursor c) {
String title = c.getString(c.getColumnIndexOrThrow(ItemDbAdapter.KEY_TITLE));
String date = c.getString(c.getColumnIndexOrThrow(ItemDbAdapter.KEY_DATE));
String imagePath = c.getString(c.getColumnIndexOrThrow(ItemDbAdapter.KEY_IMG));
int deletion = c.getInt(c.getColumnIndexOrThrow(ItemDbAdapter.KEY_DELETION));
int priority = c.getInt(c.getColumnIndexOrThrow(ItemDbAdapter.KEY_PRIORITY));
/**
* Next set the title of the entry.
*/
TextView title_text = (TextView) v.findViewById(R.id.item_text);
if (title_text != null) {
title_text.setText(title);
}
/**
* Set Date
*/
TextView date_text = (TextView) v.findViewById(R.id.item_date);
if (date_text != null) {
date_text.setText(date);
}
/**
* Decide if we should display the paper clip icon denoting image attachment
*/
ImageView item_image = (ImageView) v.findViewById(R.id.item_attachment);
item_image.setVisibility(ImageView.INVISIBLE);
if (imagePath != null && imagePath.length() != 0 && item_image != null) {
item_image.setVisibility(ImageView.VISIBLE);
}
/**
* Decide if we should display the deletion indicator
*/
ImageView del_image = (ImageView) v.findViewById(R.id.item_deletion);
del_image.setVisibility(ImageView.INVISIBLE);
if (deletion == 1) {
del_image.setVisibility(ImageView.VISIBLE);
}
}
}
XML just incase...
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#drawable/list_bg">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView android:id="#+id/item_text"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:lines="1"
android:scrollHorizontally="true"
android:ellipsize="end"
android:paddingLeft="2sp"
android:paddingTop="2sp"
android:textSize="18sp"
android:textStyle="bold"
android:shadowColor="#90909090"
android:shadowDx="1.0"
android:shadowDy="1.0"
android:shadowRadius="1.0"/>
<TextView android:id="#+id/item_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp"
android:textColor="#FF808080"
android:paddingLeft="2sp"
android:paddingTop="2sp"/>
</LinearLayout>
<ImageView android:id="#+id/item_deletion"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/deletion"
android:visibility="invisible"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:paddingRight="5sp"/>
<ImageView android:id="#+id/item_attachment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/attachment"
android:visibility="invisible"
android:layout_centerVertical="true"
android:layout_toLeftOf="#id/item_deletion"/>
</RelativeLayout>
This displays two rows of text and up to 2 images to the right of the text depending on certain conditions.
I hope this can give you a basis to work from!
Good luck :]
Check what I have done:
BTW: CheckpointsView.getImageResId() returns a valid drawable reference
public class CheckpointCursorAdapter extends ResourceCursorAdapter {
private int layoutType = 0;
public static final int BLOTTER = 1;
public static final int DAY = 2;
public static final int MONTH = 3;
public static final int OVERVIEW = 4;
public static final int LAYOUT_ID = R.layout.checkpoint_row;
public CheckpointCursorAdapter(Context context, int layoutType, Cursor cursor) {
super(context, LAYOUT_ID, cursor);
this.layoutType = layoutType;
}
#Override
public View newView(Context context, Cursor cur, ViewGroup parent) {
LayoutInflater li = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
return li.inflate(LAYOUT_ID, parent, false);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
TextView tvListText = (TextView) view.findViewById(R.id.txtCheckPoint);
Date dt = new Date(cursor.getLong(cursor.getColumnIndex(DatabaseHelper.KEY_CHECKPOINT)));
switch (layoutType) {
case BLOTTER:
tvListText.setText(dt.toLocaleString());
((ImageView) view.findViewById(R.id.imgCheckpointInOut))
.setImageResource(CheckpointsView.getImageResId(cursor.getCount()
- cursor.getPosition()));
break;
case DAY:
tvListText.setText(new SimpleDateFormat("HH:mm:ss").format(dt));
((ImageView) view.findViewById(R.id.imgCheckpointInOut))
.setImageResource(CheckpointsView.getImageResId(cursor.getPosition() + 1));
break;
case MONTH:
tvListText.setText(new SimpleDateFormat("MMM dd HH:mm:ss").format(dt));
((ImageView) view.findViewById(R.id.imgCheckpointInOut))
.setImageResource(CheckpointsView.getImageResId(cursor.getPosition() + 1));
break;
case OVERVIEW:
break;
}
}
}
And the XML just in case
<?xml version="1.0" encoding="utf-8"?>
<TextView android:id="#+id/txtCheckPoint"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textSize="20dp" android:padding="8dp" android:textStyle="bold">
</TextView>
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content" android:orientation="horizontal"
android:gravity="right" android:layout_weight="1"
android:layout_marginRight="8px">
<TextView android:id="#+id/txtTotalHours"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textSize="20dp" android:padding="8dp" android:paddingRight="12dp">
</TextView>
<TextView android:id="#+id/txtHourBalanceRow"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textSize="12dp" android:padding="8dp">
</TextView>
<ImageView android:id="#+id/imgCheckpointInOut"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:src="#drawable/black_clock" />
</LinearLayout>
You can check the whole code at:
http://code.google.com/p/droidtimesheet/
Adding images and text is not specific to CursorAdapter; you use the same technique for any kind of adapter. You can create a layout for your row and inflate it inside your getView method. The APIDemos sample project, contained in the Android SDK android-sdk-PLATFORM/samples/android-XY/ApiDemos folder, does what you want. You can find the row definitons in list_item_icon_text.xml. Here is copy of file content (w/o the license).
<?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">
<ImageView android:id="#+id/icon"
android:layout_width="48dip"
android:layout_height="48dip" />
<TextView android:id="#+id/text"
android:layout_gravity="center_vertical"
android:layout_width="0dip"
android:layout_weight="1.0"
android:layout_height="wrap_content" />
</LinearLayout>
Here is a great tutorial that I have used before to help with my custom list adapters. It sounds like it is doing the exact same thing you want to do. The tutorial shows how to build a custom list adapter with an image and two lines of text.