I am very new to android development and I feel like this is very simple, yet, I haven't managed to find anyone on google with the same problem.
I have a Gridview that is filled with a TextView (which has an image on top) and an ImageButton (to delete the current item). What I want to do is to remove the item of which I click the ImageButton.
Here is my Main :
public class ActivityMain extends Activity
{
GridView gridview;
public GridAdapter mainActivityAdapter;
public ArrayList<String> listService = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listService.add("Market");
listService.add("Recherche");
listService.add("Quiz");
gridview = (GridView) findViewById(R.id.mainActivity_grid);
mainActivityAdapter = new GridAdapter(this.getApplicationContext(), listService);
gridview.setAdapter(mainActivityAdapter);
}
}
And here is my Adapter :
public class GridAdapter extends BaseAdapter
{
Context context;
ArrayList<String> list = new ArrayList<String>();
GridAdapter adapter = this;
public GridAdapter(Context context, ArrayList<String> list)
{
this.context = context;
this.list = list;
}
#Override
public int getCount()
{
return list.size();
}
#Override
public Object getItem(int arg0)
{
return null;
}
#Override
public long getItemId(int arg0)
{
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
if(convertView==null)
{
convertView = LayoutInflater.from(context).inflate(R.layout.item_gridmain, null);
holder = new ViewHolder();
holder.textView = (TextView) convertView.findViewById(R.id.gridMain_text);
holder.close = (ImageButton) convertView.findViewById(R.id.mainActivity_delete);
convertView.setTag(holder);
}
else{
holder = (ViewHolder) convertView.getTag();
}
// Doing stuff on views
holder.close.setOnClickListener(new View.OnClickListener()
{
public void onClick(View arg1)
{
// list.remove(position);
list.remove(position);
adapter.notifyDataSetChanged();
}
});
return convertView;
}
public static class ViewHolder
{
TextView textView;
ImageButton close;
}
}
The thing is, when I click on one ImageButton, it's always the last item that has been added that is being removed and I can't figure out why or how to fix this.
Thank you.
==================
EDIT :
Here is my activity_main.xml :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/main_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#DDDDDD"
android:orientation="vertical" >
<GridView
android:id="#+id/mainActivity_grid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="5sp"
android:layout_marginRight="5sp"
android:layout_marginTop="5sp"
android:clickable="false"
android:gravity="center"
android:horizontalSpacing="15dp"
android:numColumns="2"
android:stretchMode="columnWidth"
android:verticalSpacing="10dp" />
</LinearLayout>
And my item_gridmain.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:orientation="vertical" >
<TextView
android:id="#+id/gridMain_text"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center"
android:textAlignment="center"
android:textColor="#android:color/holo_blue_dark"
/>
<ImageButton
android:id="#+id/mainActivity_delete"
style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:contentDescription="#string/deleteFav"
android:src="#drawable/boutoncroixfermer" />
</RelativeLayout>
You have ImageButton's in every item right? You can set
holder.close.setTag(Integer.valueOf(position));
And then, you have all positions hidden in the right buttons.Change the OnClickListener like below:
close.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
list.remove((Integer) v.getTag());
adapter.notifyDataSetChanged();
}
});
Ok actually it was my own mistake and I feel incredibly dumb now.
I was actually removing the right item but in each view I was replacing each item at position with what was there in the first place. So each item was the correct one but the picture/text were the old one because I was modifying them inside getView().
Sorry for that lose of time, my bad, I want to punch myself now.
Please use ViewHolder pattern, and also add your gridMain_text.xml
else you will keep receiving wrong index of click
http://www.binpress.com/tutorial/smooth-out-your-listviews-with-a-viewholder/9
This is example of ListView but equally applicable for GridView
Please use
holder.close.setOnClickListener(new View.OnClickListener()
{
public void onClick(View arg1)
{
// list.remove(position);
list.remove(position);
adapter.notifyDataSetChanged();
}
});
instead of close.setOnClickListener, i ran your this code an now it work fine
add Log.debug() in listener to ensure the remove position is right.
How do you know after click,the last item is removed?I mean,if there has text label in item view?Maybe you remove the right item,but after gridview refresh,it looks like the last item is removed.
You can add position label with setText in getView.That may helps you.
Ok,I know.Where did you do render item view?You must do it in getView.The AdapterView cached it's item view.As you removed the right position.May be the position is not the right view.You can run hierarchyviewer to detect what happen.
Related
I am new to android programming and this task is really need for my school project. Please kindly help me.
I've string array List - (retrieved from csv)
list = new ArrayList<>(Arrays.asList("111,222,333,444,555,666".split(",")));
myList.setAdapter(new ArrayAdapter<String>(getActivity(),R.layout.cell,list));
The result is showing only line by line text of arrayList. I want to add button to each generated line by line to delete clicked row.
Please how can I do this. Thank you for understanding my problem.
You have to create a custom layout xml which having a single item then you will add your button to this layout along with any other items.
CustomLayout.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" >
<TextView
android:id="#+id/tvContact"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textStyle="bold" />
<Button
android:id="#+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Call" />
</RelativeLayout>
Now after creating custom item layout you need listview which holds all items.
MainActivity.xml
.
.
<ListView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
.
.
Now in java file just set adapter with our custom layout xml
.
.
list = new ArrayList<String>(Arrays.asList("111,222,333,444,555,666".split(",")));
listview.setAdapter(new MyCustomAdapter(list, context) );
.
.
Custom adapter Class
public class MyCustomAdapter extends BaseAdapter implements ListAdapter {
private ArrayList<String> list = new ArrayList<String>();
private Context context;
public MyCustomAdapter(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);
}
#Override
public long getItemId(int pos) {
return list.get(pos).getId();
//just return 0 if your list items do not have an Id variable.
}
#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.CustomLayout, null);
}
//Handle TextView and display string from your list
TextView tvContact= (TextView)view.findViewById(R.id.tvContact);
tvContact.setText(list.get(position));
//Handle buttons and add onClickListeners
Button callbtn= (Button)view.findViewById(R.id.btn);
callbtn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
//do something
}
});
addBtn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
//do something
notifyDataSetChanged();
.
}
});
return view;
}
}
We have need ListviewActivity for listing your data
SchoolAdapter which is custom adapter to inflate each individual row
activity_listview which is layout for ListviewActivity
view_listview_row which is required for each individual row
Now create all file as below
For ListviewActivity,
public class ListviewActivity extends AppCompatActivity {
private ListView mListview;
private ArrayList<String> mArrData;
private SchoolAdapter mAdapter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_listview);
mListview = (ListView) findViewById(R.id.listSchool);
// Set some data to array list
mArrData = new ArrayList<String>(Arrays.asList("111,222,333,444,555,666".split(",")));
// Initialize adapter and set adapter to list view
mAdapter = new SchoolAdapter(ListviewActivity.this, mArrData);
mListview.setAdapter(mAdapter);
mAdapter.notifyDataSetChanged();
}
For SchoolAdapter,
public class SchoolAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<String> mArrSchoolData;
public SchoolAdapter(Context context, ArrayList arrSchoolData) {
super();
mContext = context;
mArrSchoolData = arrSchoolData;
}
public int getCount() {
// return the number of records
return mArrSchoolData.size();
}
// getView method is called for each item of ListView
public View getView(int position, View view, ViewGroup parent) {
// inflate the layout for each item of listView
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.view_listview_row, parent, false);
// get the reference of textView and button
TextView txtSchoolTitle = (TextView) view.findViewById(R.id.txtSchoolTitle);
Button btnAction = (Button) view.findViewById(R.id.btnAction);
// Set the title and button name
txtSchoolTitle.setText(mArrSchoolData.get(position));
btnAction.setText("Action " + position);
// Click listener of button
btnAction.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Logic goes here
}
});
return view;
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}}
For activity_listview,
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#D1FFFF"
android:orientation="vertical">
<ListView
android:id="#+id/listSchool"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:divider="#0000CC"
android:dividerHeight="0.1dp"></ListView>
For view_listview_row,
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="7.5dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:paddingTop="7.5dp">
<TextView
android:id="#+id/txtSchoolTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="2dp"
android:text="TextView"
android:textColor="#android:color/black"
android:textSize="20dp" />
<Button
android:id="#+id/btnAction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:text="Click Me" />
At last but not least, do not forgot to add your activity in manifest.xml
Create a custom list view in another file with the only content of each item in the list.
Then create a Custom Adapter extending BaseAdapter and bind it.
Please refer to this website for example.
https://looksok.wordpress.com/tag/listview-item-with-button/
OR
http://www.androidhive.info/2012/02/android-custom-listview-with-image-and-text/
I using custom adapter for displaying a list of items in my project,
Right now it is working fine.but now i got another requirement that i need to put a button on each item.
If put the button like that then the onItemClickListenter() for that item is not working ,instead onClickListener() for that button is working.
But according to my context both onClickListenter() for button and onItemClickListener() for that item should work.Can somebody please help me if know the technique.
Thanks in advance.
As Button is a focusable view thats why onItemClick isn't work. In ur_row.xml (where you placed that Button) add these attributes inside Button tag
android:focusable="false"
android:focusableInTouchMode="false"
Inside your CustomAdapter's getView(...) set onClickListener for that Button this will fire both onItemClick for ListView and onClick for Button.
You need a custom adapter:
This project contains 4 parts:
1.MainActivity
public class MainActivity extends Activity {
private ListView listView;
private CustomAdapter customAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_activity);
init();
}
/**
* Init Data
*/
public void init(){
List<String> listItems = new ArrayList<String>();
for(int i=0;i<10;i++) {
listItems.add("Test" + i);
}
listView = (ListView)findViewById(R.id.listView);
customAdapter = new CustomAdapter(MainActivity.this,R.layout.row_item,listItems);
listView.setAdapter(customAdapter);
}
}
2.MainActivity layout
<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=".main_activity">
<ListView
android:id="#+id/listView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
3.CustomAdapter
public class CustomAdapter extends ArrayAdapter<String> {
private Context context;
private TextView itemListText;
private Button itemButton;
private List<String> listValues;
public CustomAdapter(Context context, int resource, List<String> listValues) {
super(context, resource,listValues);
this.context = context;
this.listValues = listValues;
}
/**
* getView method is called for each item of ListView
*/
#Override
public View getView(int position, View convertView, ViewGroup parent) {
String currentValue = listValues.get(position);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.row_item, null);
itemListText = (TextView)convertView.findViewById(R.id.itemListText);
itemListText.setText(currentValue);
itemListText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context,"Text Working",Toast.LENGTH_SHORT).show();
}
});
itemButton = (Button)convertView.findViewById(R.id.itemButton);
//To lazy to implement interface
itemButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context,"Button Working",Toast.LENGTH_SHORT).show();
}
});
return convertView;
}
}
4.Row Item layout
<?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="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/itemListText"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Select Text"
android:gravity="center_vertical"
android:layout_weight="0.7"/>
<Button
android:id="#+id/itemButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Push me"
/>
</LinearLayout>
Output:
TextView touch action
Button touch action
rather than putting buttons on row use image views as many required and set on click listener to them, Since imageViews are not focusable
I have a list view every item in list contains textviews and button what I want is when I click on the button of any item in list I want to printout the position of button if i clicked the button in first line i want to print out 0 and go on but it doesn't work
this is my method to display view
private void displayListView() {
Cursor cursor = dbHelper.fetchAllCountries();
// The desired columns to be bound
String[] columns = new String[] {
PhonesDbAdapter.KEY_NAME,
PhonesDbAdapter.KEY_CONTINENT,
};
// the XML defined views which the data will be bound to
int[] to = new int[] {
R.id.continent,
R.id.name
};
// create the adapter using the cursor pointing to the desired data
//as well as the layout information
dataAdapter = new SimpleCursorAdapter(
this, R.layout.phone_layout,
cursor,
columns,
to,
0);
listView = (ListView) findViewById(R.id.listView1);
// Assign adapter to ListView
listView.setAdapter(dataAdapter);
}
public void print(View v)
{
}
and here how my item look like
<?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="vertical"
android:padding="6dip"
android:background="#f0f0f0" >
<TextView
android:id="#+id/continent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:textColor="#275a0d"/>
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="TextView"
android:textColor="#000"/>
<Button
android:id="#+id/button1"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:background="#drawable/ic_launcher"/>
<Button
android:id="#+id/call"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/button1"
android:background="#drawable/ic_launcher"
android:onClick="print"/>
</RelativeLayout>
and this the layout that contain the listview
<?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:orientation="vertical"
android:background="#f0f0f0">
<EditText android:id="#+id/myFilter" android:layout_width="match_parent"
android:layout_height="wrap_content" android:ems="10">
</EditText>
<ListView android:id="#+id/listView1" android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
i spent alot of time with this problem and i hope that u can help me and im really sorry for my bad english
Are you implementing the method getView() on your adapter?
That's where you want to add the OnClickListener to your Button
Once you do that you can set the position as the tag of the Button and retrieve it on the onClick method.
Something like this:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.your_item_layout, parent, false);
Button myButton = (Button) row.findViewById(R.id. call);
myButton.setOnClickListener(new OnClickListener {
#Override
public void onClick(View view) {
int position = (int)view.getTag();
//Do whatever you want with the position here
}
});
myButton.setTag(position);
return row;
}
From last 3 three years I am not working on android so I am not sure my suggestion is correct or not. You need to test it for you purpose.
In your above case you cannot use onItemClickListner because it can only be used when you are tracking your complete list row. What I think is you can create a custom adapter and override its getView method. In getView method you will have your position and you can set button click listner for you button in getview. So In this way you can get your button position.
You try it once if you need some code then I can try to write it for you...
THIS IS HOW YOU CAN CREATE CUSTOM ADAPTER.
public class my_custom_adapter extends ArrayAdapter<String> {
private Context context = null;
ArrayList<String> elements = null;
public my_custom_adapter(Context context, int type, ArrayList<String> elements)
{
super(context, type, elements);
this.elements = elements;
this.context = context;
}
//THIS IS SIMPLY A CLASS VIEW WILL HOLD DIFFERENT VIEWS OF YOUR ROW.
static class ViewHolder
{
public TextView tv;
public Button cb;
}
#Override
public View getView (final int position, View convertView, ViewGroup parent)
{
View rowView = convertView;
ViewHolder holder = null;
if (rowView == null) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
// HERE I AM INFLATING LISTVIEW LAYOUT.
rowView = inflater.inflate(R.layout.inflated_layout, null, false);
holder = new ViewHolder();
holder.cb = (Button) rowView.findViewById(R.id.checkBox1);
holder.tv = (TextView) rowView.findViewById(R.id.textView1);
rowView.setTag(holder);
} else {
holder = (ViewHolder) rowView.getTag();
}
if (holder != null) {
holder.cb.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// IF YOUR BUTTON TAG HERE AND YOU CAN HAVE POSITION USING "position" PARAMETER
}
});
}
return rowView;
}
}
My main purpose is to make some buttons inside a listview, to change the state of some images (inside listview items too).
So I worked out this code, creating a custom adapter like this one:
public class CategoriesGridViewAdapter extends BaseAdapter {
private Activity context;
private List<CategoryHolder> mCategoriesList = new ArrayList<CategoryHolder>();
private CategoryHolder mCategoryHolder;
// #SuppressLint("UseSparseArrays")
// private Map<Integer, Boolean> favVisibilitiesMap = new HashMap<Integer,
// Boolean>();
// #SuppressLint("UseSparseArrays")
// private Map<Integer, Boolean> cartVisibilitiesMap = new HashMap<Integer,
// Boolean>();
private ViewHolder holder = null;
private int[] mTestingImagesForCategories = new int[] { R.drawable.pic1,
R.drawable.pic2, R.drawable.pic3, R.drawable.pic4, R.drawable.pic5
};
public CategoriesGridViewAdapter(Activity activity,
List<CategoryHolder> categoriesList) {
this.context = activity;
this.mCategoriesList = categoriesList;
}
#Override
public int getCount() {
return mCategoriesList.size();
}
#Override
public Object getItem(int pos) {
return mCategoriesList.get(pos);
}
#Override
public long getItemId(int arg0) {
return 0;
}
#Override
public View getView(int pos, View convertView, ViewGroup parent) {
mCategoryHolder = mCategoriesList.get(pos);
if (convertView == null) {
convertView = context.getLayoutInflater().inflate(
R.layout.cell_categories_gridview, parent, false);
holder = new ViewHolder(convertView);
holder.btn_cell_categoryAddCart
.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int getPosition = (Integer) v.getTag();
CategoryHolder localCategoryHolder = mCategoriesList
.get(getPosition);
localCategoryHolder.setCartVisible(!mCategoriesList
.get(getPosition).isCartVisible());
holder.iv_cell_categoryCart
.setVisibility(setImageVisibility(localCategoryHolder
.isCartVisible()));
}
});
holder.btn_cell_categoryAddFav
.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int getPosition = (Integer) v.getTag();
CategoryHolder localCategoryHolder = mCategoriesList
.get(getPosition);
localCategoryHolder.setFavVisible(!mCategoriesList
.get(getPosition).isFavVisible());
holder.iv_cell_categoryFav
.setVisibility(setImageVisibility(localCategoryHolder
.isFavVisible()));
}
});
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.btn_cell_categoryAddCart.setTag(pos);
holder.btn_cell_categoryAddFav.setTag(pos);
holder.iv_cell_categoryCart
.setVisibility(setImageVisibility(mCategoryHolder
.isCartVisible()));
holder.iv_cell_categoryFav
.setVisibility(setImageVisibility(mCategoryHolder
.isFavVisible()));
// just for testing, the final images will be some bitmaps downloaded from a server
holder.iv_cell_categoryContent
.setBackgroundResource(mTestingImagesForCategories[pos]);
return convertView;
}
private int setImageVisibility(boolean isVisible) {
return (isVisible) ? View.VISIBLE : View.INVISIBLE;
}
static class ViewHolder {
public ImageView iv_cell_categoryCart;
public ImageView iv_cell_categoryFav;
public ImageView iv_cell_categoryContent;
public Button btn_cell_categoryAddFav;
public Button btn_cell_categoryAddCart;
public ViewHolder(View convertView) {
iv_cell_categoryContent = (ImageView) convertView
.findViewById(R.id.iv_cell_category_image);
iv_cell_categoryCart = (ImageView) convertView
.findViewById(R.id.iv_cell_category_cart);
iv_cell_categoryFav = (ImageView) convertView
.findViewById(R.id.iv_cell_category_fav);
btn_cell_categoryAddFav = (Button) convertView
.findViewById(R.id.btn_cell_category_add_fav);
btn_cell_categoryAddCart = (Button) convertView
.findViewById(R.id.btn_cell_category_add_cart);
}
}
}
I just don't understand what is wrong with my code?!
I have this adapter, which I debugged and everything is working ok (changes the boolean state of those images I placed inside the layout), but:
1.
it doesn't make the images( holder.iv_cell_categoryCart, holder.iv_cell_categoryFav) visible / invisible. What could the problem be? (problem solved using notifyDataSetChanged in each setOnClickListener.. yeah I know.. stupid me )
2.
those static images (mTestingImagesForCategories -- R.drawable.pic1,
R.drawable.pic2, R.drawable.pic3, R.drawable.pic4, R.drawable.pic5) are not ever shown.
The layout for this GridView looks like this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView
android:id="#+id/iv_cell_category_image"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#+id/lay_cell_category_content"
android:layout_below="#+id/lay_cell_category_header"
android:background="#drawable/ic_launcher"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingTop="5dp"
android:scaleType="fitXY" />
<RelativeLayout
android:id="#+id/lay_cell_category_header"
android:layout_width="fill_parent"
android:layout_height="#dimen/activity_categories_gridview_cornerimage_height"
android:layout_alignParentTop="true" >
<ImageView
android:id="#+id/iv_cell_category_fav"
android:layout_width="#dimen/activity_categories_gridview_cornerimage_width"
android:layout_height="fill_parent"
android:layout_above="#+id/lay_cell_category_content"
android:layout_alignParentLeft="true"
android:background="#drawable/carti" />
<ImageView
android:id="#+id/iv_cell_category_cart"
android:layout_width="#dimen/activity_categories_gridview_cornerimage_width"
android:layout_height="fill_parent"
android:layout_alignParentRight="true"
android:background="#drawable/star" />
</RelativeLayout>
<LinearLayout
android:id="#+id/lay_cell_category_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal" >
<Button
android:id="#+id/btn_cell_category_add_cart"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:focusable="false"
android:focusableInTouchMode="false"
android:text="Add Cart"
android:textSize="12sp" />
<Button
android:id="#+id/btn_cell_category_add_fav"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:focusable="false"
android:focusableInTouchMode="false"
android:text="Add Fav"
android:textSize="12sp" />
</LinearLayout>
The idea of this layout is to have a layout main content of an image, with 2 bottom buttons which makes 2 smalls images at the top right and left of the layout visible/invisible.
(If user presses on Add Fav, the top right image consisting of a star will be visible. If he presses it again, the image will become invisible -- simulating adding / removing product to favorites). Please any help is appreciated!
LE: I should probably mention that I'm creating the GridView programmatically, inside a Fragment (used in a ViewPager).
Looks like the problem was with the mCategoriesList.. it was null when setting adapter in the activity, and I was initialising it after that, causing it to show only the static content of the gridview cell layout (2 buttons and 2 non-changeable images).
I have written code for gridview in which i can show image and text but i want to show all image in single scrollable row like Pulse news apps.
I have implemented horizontalscroll-view for gridview in xml but it does not work at all.
I am using pageviwer for tabs and i am using fragments.
Here is my xml code
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<HorizontalScrollView
android:id="#+id/horizontalScrollView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:scrollbars="horizontal" >
<GridView
android:layout_width="500dp"
android:layout_height="400dp"
android:id="#+id/gridview"
android:columnWidth="300dp"
android:numColumns="3"
android:horizontalSpacing="10dp"
android:scrollbars="horizontal">
</GridView>
</HorizontalScrollView>
</RelativeLayout>
Here is my image adpator code
public class ImageAdapter extends BaseAdapter {
private Context context;
private final String[] mobileValues;
private TextView t;
public ImageAdapter(Context context, String[] mobileValues) {
this.context = context;
this.mobileValues = mobileValues;
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridView;
if (convertView == null) {
gridView = new View(context);
// get layout from mobile.xml
gridView = inflater.inflate(R.layout.showlist_item, null);
// set value into textview
TextView textView = (TextView) gridView
.findViewById(R.id.grid_item_label);
textView.setText(mobileValues[position]);
// set image based on selected text
ImageView imageView = (ImageView) gridView
.findViewById(R.id.grid_item_image);
String mobile = mobileValues[position];
if (mobile.equals("Windows")) {
imageView.setImageResource(R.drawable.test_play_image);
} else if (mobile.equals("iOS")) {
imageView.setImageResource(R.drawable.test_play_image);
} else if (mobile.equals("Blackberry")) {
imageView.setImageResource(R.drawable.test_play_image);
} else {
imageView.setImageResource(R.drawable.test_play_image);
}
} else {
gridView = (View) convertView;
}
return gridView;
}
private void clickedButton(TextView tv){
int num = Integer.parseInt(tv.getText().toString());
++num;
tv.setText(Integer.toString(num));
}
private void clickedButtonm(TextView tv){
int num = Integer.parseInt(tv.getText().toString());
if(num>0){
--num;
tv.setText(Integer.toString(num));
}
}
public int getCount() {
return mobileValues.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
class MyOnClickListener implements OnClickListener{
public final TextView tv;
public MyOnClickListener(TextView tv){
this.tv=tv;
}
public void onClick(View v) {
// TODO Auto-generated method stub
clickedButton(tv);
}
}
class MyOnClickListenerm implements OnClickListener{
public final TextView tv;
public MyOnClickListenerm(TextView tv){
this.tv=tv;
}
public void onClick(View v) {
// TODO Auto-generated method stub
clickedButtonm(tv);
}
}
I want to display like this scrollable to right.
There is a nice solution in Android from now on (as Zainodis has said in its comment ) : HorizontalGridView.
1. Gradle dependency
dependencies {
compile 'com.android.support:leanback-v17:23.1.0'
}
2. Add it in your layout
your_activity.xml
<!-- your stuff before... -->
<android.support.v17.leanback.widget.HorizontalGridView
android:layout_width="wrap_content"
android:layout_height="80dp"
android:id="#+id/gridView"
/>
<!-- your stuff after... -->
3. Layout grid element
Create a layout for your grid element ( grid_element.xml ). I have created a simple one with only one button in it.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button"
android:id="#+id/button" />
</LinearLayout>
4. Create an adapter
Highly inspired by this link : https://gist.github.com/gabrielemariotti/4c189fb1124df4556058
public class GridElementAdapter extends RecyclerView.Adapter<GridElementAdapter.SimpleViewHolder>{
private Context context;
private List<String> elements;
public GridElementAdapter(Context context){
this.context = context;
this.elements = new ArrayList<String>();
// Fill dummy list
for(int i = 0; i < 40 ; i++){
this.elements.add(i, "Position : " + i);
}
}
public static class SimpleViewHolder extends RecyclerView.ViewHolder {
public final Button button;
public SimpleViewHolder(View view) {
super(view);
button = (Button) view.findViewById(R.id.button);
}
}
#Override
public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View view = LayoutInflater.from(this.context).inflate(R.layout.grid_element, parent, false);
return new SimpleViewHolder(view);
}
#Override
public void onBindViewHolder(SimpleViewHolder holder, final int position) {
holder.button.setText(elements.get(position));
holder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(context, "Position =" + position, Toast.LENGTH_SHORT).show();
}
});
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemCount() {
return this.elements.size();
}
}
5. Initialize it in your activity :
private HorizontalGridView horizontalGridView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_activity);
horizontalGridView = (HorizontalGridView) findViewById(R.id.gridView);
GridElementAdapter adapter = new GridElementAdapter(this);
horizontalGridView.setAdapter(adapter);
}
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_below="#+id/seatLegendLayout">
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/linearLayout_gridtableLayout"
android:layout_width="900dp"
android:layout_height="match_parent"
android:orientation="horizontal">
<GridView
android:id="#+id/gridView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="4dp"
android:columnWidth="100dp"
android:gravity="center"
android:numColumns="9"
android:horizontalSpacing="1dp"
android:scrollbarAlwaysDrawHorizontalTrack="true"
android:scrollbarAlwaysDrawVerticalTrack="true"
android:scrollbars="horizontal"
android:stretchMode="none"
android:verticalSpacing="1dp">
</GridView>
</LinearLayout>
</FrameLayout>
</HorizontalScrollView>
I found Two-way GridView helpful on github.
It has some methods:
scrollDirectionPortrait (vertical | horizontal)
scrollDirectionLandscape (vertical | horizontal)
numRows()
etc
There is a better cleaner working solution that i have tested without any kind of extra dependencies just change your layout xml something similar like below .
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<android.support.v7.widget.RecyclerView
android:id="#+id/horizontal_grid_view"
android:layout_width="wrap_content"
android:layout_height="112dp"
android:scrollbarAlwaysDrawVerticalTrack="true"></android.support.v7.widget.RecyclerView>
</HorizontalScrollView>
Also setSpan count based on your requirement while assigning Grid layout manager.
I don't think that gridviews can be made horizontally scrollable. Android has provided galleryView for this purpose. You can use that. Here is a thead that can help you making galleryView work as a horizontal gridview:-
Horizontal scrolling in android gridview
The library Android-DraggableGridViewPager by Justin(zzhouj)
Provides the following features
Grid view layout split into pages.
Horizontally swipe pages like ViewPager in support-v4 library.
Setting col & row count.
Setting listeners for: page change, item
click, item long click, rearrange.
Helped me create a horizontal scroll-able grid with page indicators, hope it helps someone trying to implement something similar.
You can use recyclerView as an GridView no need to use GridView if it's difficult for you. Have a look below
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvQuickAccess"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:spanCount="2"
android:gravity="center"
android:orientation="horizontal"
tools:listitem="#layout/layout_item"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
android:scrollbarAlwaysDrawHorizontalTrack="true"/>
You can set number of columns by app:spanCount = " ". Don't forget to set layoutManager as GridLayoutManager and orientation "Horizontal"
For a small set of data, a fine route would be to use a layout such as below for your container:
<HorizontalScrollView
android_id="#+id/scroll_view"
android_width="match_parent"
android_height="wrap_content">
<LinearLayout
android_id="#+id/my_list"
android_width="wrap_content"
android_height="wrap_content" >
</LinearLayout>
</HorizontalScrollView>
a different layout for your list items (list_item.xml):
<FrameLayout
android_id="#+id/item_container"
android_width="100dp"
android_height="100dp">
<ImageView
android_id="#+id/item_background"
android_width="match_parent"
android_height="match_parent" />
<TextView
android_id="#+id/item_title"
android_width="match_parent"
android_height="50dp"
android_background="#80000000"
android_gravity="center_vertical" />
</FrameLayout>
and then programatically add views as needed:
public void addItensToLayout(String... mobileValues, LayoutInflater inflater) {
LinearLayout list = (LinearLayout) findViewById(R.id.my_list);
for (String item : mobileValues) {
FrameLayout item = inflater.inflate(R.layout.list_item, list, false);
TextView textView = (TextView) gridView
.findViewById(R.id.item_title);
textView.setText(item);
ImageView imageView = (ImageView) item
.findViewById(R.id.item_background);
String mobile = mobileValues[position];
if (mobile.equals("Windows")) {
imageView.setImageResource(R.drawable.test_play_image);
} else if (mobile.equals("iOS")) {
imageView.setImageResource(R.drawable.test_play_image);
} else if (mobile.equals("Blackberry")) {
imageView.setImageResource(R.drawable.test_play_image);
} else {
imageView.setImageResource(R.drawable.test_play_image);
}
list.addView(item);
}
}
By doing so, you are not longer using an adapter. If you really need to use an adapter, you should use an ViewPager, there is plenty of info for doing so in android documentation, or you can start right here in StackOverflow:
Using viewpager in my application
android viewPager implementation
Please ask for more info if I missed any point back there.