Grid style menu inside grid cell on longpress - android

I am trying to achieve something similar to this :
When a user long press on a grid cell in a grid-view the menu should be drawn inside the grid cell area as shown above. Please help me if anyone has ever tried something similar to this or if there are any libraries available to do the same.
Here is a code snippet on how generally a context-menu is triggered on long-press.
My Activity class :
public class GridViewActivity extends Activity {
GridView gridView;
ImageAdapter mImageAdapter;
static final String[] MOBILE_OS = new String[] {
"Android", "iOS", "Windows", "Blackberry"
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mImageAdapter = new ImageAdapter(this, MOBILE_OS);
gridView = (GridView)findViewById(R.id.gridView1);
registerForContextMenu(gridView);
gridView.setAdapter(mImageAdapter);
gridView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
Toast.makeText(getApplicationContext(),
((TextView)v.findViewById(R.id.grid_item_label)).getText(),
Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void onCreateContextMenu(ContextMenu iMenu, View iView, ContextMenuInfo iMenuInfo) {
super.onCreateContextMenu(iMenu, iView, iMenuInfo);
iMenu.setHeaderTitle("OPTIONS");
iMenu.clear();
iMenu.add(Menu.NONE, 0, Menu.NONE, "VIEW");
iMenu.add(Menu.NONE, 1, Menu.NONE, "EDIT");
iMenu.add(Menu.NONE, 2, Menu.NONE, "SHARE");
iMenu.add(Menu.NONE, 3, Menu.NONE, "DELETE");
}
ImageAdapter class :
public class ImageAdapter extends BaseAdapter {
private Context context;
private final String[] mobileValues;
public LayoutInflater inflater;
public LinearLayout linearLayout;
public ImageAdapter(Context context, String[] mobileValues) {
this.context = context;
this.mobileValues = mobileValues;
}
public View getView(int position, View convertView, ViewGroup parent) {
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.mobile, null);
// set value into textview
linearLayout = (LinearLayout)gridView.findViewById(R.id.linear1);
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.windows_logo);
} else if (mobile.equals("iOS")) {
imageView.setImageResource(R.drawable.ios_logo);
} else if (mobile.equals("Blackberry")) {
imageView.setImageResource(R.drawable.blackberry_logo);
} else {
imageView.setImageResource(R.drawable.android_logo);
}
} else {
gridView = (View) convertView;
}
return gridView;
}
#Override
public int getCount() {
return mobileValues.length;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
}
main.xml :
<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gridView1"
android:numColumns="auto_fit"
android:gravity="center"
android:columnWidth="100dp"
android:stretchMode="columnWidth"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</GridView>
mobile.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:orientation="vertical" >
<ImageView
android:id="#+id/grid_item_image"
android:layout_width="50px"
android:layout_height="50px"
android:layout_marginRight="10px"
android:src="#drawable/android_logo" >
</ImageView>
<TextView
android:id="#+id/grid_item_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#+id/label"
android:layout_marginTop="5px"
android:textSize="15px" >
</TextView>
</LinearLayout>
What am trying to achieve here is that on long-press on a grid cell it should replace this particular grid cell view with the above view and each of the boxes (i.e. view, edit, share and delete) shall respond to some event listener.

I would imagine doing something like this would be on a bigger screen right? But I guess you could maybe make each grid cell a RelativeLayout and house whatever is there. Then when you long press, add another view, probably a LinearLayout that houses 4 TextViews that say what you want it to say. Since whatever the lowest level View in a Relative layout produces sort of a floating effect, it could work. Plus you can add opaqueness to make it see through. Oh and I should probably add that Android comes with long press and letting go features so this shouldn't be too bad to implement.

Related

OnItemClickListener not working but OnItemLongClickListener is working on GridView

I am having a problem with a clickListener on my gridview. The LongClickListener works without issue. But I cannot seem to get any response from the click Listener.
My code is below.
Im confused as to why the long click works but not the normal click,
Any pointers would be appreciated
Thanks
final GridView gridView = (GridView) findViewById(R.id.grid_view);
gridView.setNumColumns(numOfColumns);
gridView.getLayoutParams().width = (CELL_WIDTH * numOfColumns);
gridView.getLayoutParams().height = (CELL_WIDTH * numOfRows);
....
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
Log.d("ABCD", "Position Single Click is " + position);
// Ideally in here I want to put to open a soft keyboard for the user to enter a value
// InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
// imm.showSoftInput(gridView, InputMethodManager.SHOW_IMPLICIT);
}
});
gridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
Log.d("ABCD", "Position Long Click is " + position);
return true;
}
});
grid_view is
<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:descendantFocusability="blocksDescendants"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="horizontal">
<View
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"/>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/my_grid_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"/> <<--- I WANT THIS TO GET THE CLICK
<View
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"/>
</LinearLayout>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/listId"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp" />
</LinearLayout>
GridCell in the grid view is
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:padding="0dp" android:layout_margin="0dp"
android:focusable="false"
android:clickable="false"
android:focusableInTouchMode="false"
>
<TextView
android:id="#+id/grid_item_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="1dp"
android:paddingRight="0dp"
android:paddingTop="0dp"
android:paddingBottom="0dp"
android:textSize="10px"
android:focusable="false"
android:clickable="false"
android:focusableInTouchMode="false"
>
</TextView>
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/grid_item_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#+id/celllabel"
android:background="#android:color/transparent"
android:paddingLeft="5dp"
android:paddingRight="0dp"
android:paddingTop="0dp"
android:paddingBottom="0dp"
android:layout_margin="0dp"
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="false"
android:cursorVisible="false">
</EditText>
</RelativeLayout>
The adapter class has a getView and is as below
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridView;
MyObject obj = myObjects.get(position);
if (convertView == null) {
gridView = inflater.inflate(R.layout.grid_cell, null);
String textColour = "#000000";
TextView textView = (TextView) gridView.findViewById(R.id.grid_item_label);
textView.setText(Html.fromHtml(String.format("<font color='%s'>%s</font>", textColour, obj.getValue())));
TextView superScriptTv = (TextView) gridView.findViewById(R.id.grid_item_number);
if (obj.getNumber() > 0) {
superScriptTv.setText(Html.fromHtml(String.format("<font>%s</font>", cell.getNumber())));
}
} else {
gridView = convertView;
}
gridView.setBackgroundColor(obj.getBackgroundColour());
return gridView;
}
EDIT
Really banging my head against a wall here now :)
Im updating the code sample so have more data. Ive noticed that in my adapter if I do not set the text on the textview with ID = R.id.grid_item_number then it works. As soon as I set text on it then I lose the click listener.
The linked question/answer doesnt help from what I can see. Can anyone help with my stupidity?
EDIT
Adapter code has been added.
Thanks in advance.
The problem is with the EditText inside the row_cell. When you click on the item, it takes focus and prevents the whole item to be clickable again. As you noticed, only long click works.
Here you have a similar problem.
To resolve that issue I would move your OnItemClickListeners from the Activity / Fragment to your GridViewAdapter, so instead of:
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
Log.d("ABCD", "Position Single Click is " + position);
// Ideally in here I want to put to open a soft keyboard for the user to enter a value
// InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
// imm.showSoftInput(gridView, InputMethodManager.SHOW_IMPLICIT);
}
});
gridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
Log.d("ABCD", "Position Long Click is " + position);
return true;
}
});
I would do something like that:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridViewItem;
if (convertView == null) {
gridViewItem = new View(mContext);
gridViewItem = layoutInflater.inflate(R.layout.grid_cell, null);
TextView textView = (TextView)gridViewItem.findViewById(R.id.grid_item_number);
textView.setText(mValues[position]);
EditText editText = (EditText)gridViewItem.findViewById(R.id.grid_item_label);
} else {
gridViewItem = (View) convertView;
}
gridViewItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.e("GRID", "onClick: " );
}
});
gridViewItem.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
Log.e("GRID", "onLongClick: " );
return true;
}
});
return gridViewItem;
}
It will prevent this strange behaviour you are struggling right now.
For the sake of that example please find my code below:
MainActivity layout:
<?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:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="io.github.mmbs.gridviewcheck.MainActivity"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="0dp">
<GridView
android:id="#+id/gridView"
android:numColumns="auto_fit"
android:columnWidth="100dp"
android:stretchMode="columnWidth"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true">
</GridView>
</android.support.constraint.ConstraintLayout>
Grid cell layout:
<?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="wrap_content"
android:layout_margin="0dp"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:padding="8dp">
<TextView
android:id="#+id/grid_item_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="0dp"
android:paddingLeft="1dp"
android:paddingRight="0dp"
android:paddingTop="0dp"
android:textSize="20sp"
android:text="TEXTVIEW">
</TextView>
<EditText
android:id="#+id/grid_item_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="0dp"
android:background="#android:color/transparent"
android:cursorVisible="false"
android:layout_below="#id/grid_item_number"
android:text="EDITTEXT">
</EditText>
</RelativeLayout>
Please take into consideration, that I removed all layouts attributes responsible for focusability.
MyGridAdapter:
public class MyGridViewAdapter extends BaseAdapter {
private Context mContext;
private final String[] mValues;
public MyGridViewAdapter(String[] values, Context context) {
mValues = values;
mContext = context;
}
#Override
public int getCount() {
return mValues.length;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridViewItem;
if (convertView == null) {
gridViewItem = new View(mContext);
gridViewItem = layoutInflater.inflate(R.layout.grid_cell, null);
TextView textView = (TextView)gridViewItem.findViewById(R.id.grid_item_number);
textView.setText(mValues[position]);
EditText editText = (EditText)gridViewItem.findViewById(R.id.grid_item_label);
} else {
gridViewItem = (View) convertView;
}
gridViewItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.e("GRID", "onClick: " );
}
});
gridViewItem.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
Log.e("GRID", "onLongClick: " );
return true;
}
});
return gridViewItem;
}
}
If you like, I can also share this code on github, so you will have a fully operational example.
The second option is to leave your implementation as it is and do hacks when the EditText is focusable and enabled. Here you have related topics:
Android: Force EditText to remove focus?
ListView items focus behaviour
Focusable EditText inside ListView
Android: Force EditText to remove focus?
What is more, please take into account that answer:
Do not use clickable objects in the grid. In that case Android cannot handle the click event of GridView.
Instead, use something to show a similar user interface view. Then handle that object's click actions.
Don't: put Button in the GridView to perform some click actions.
Do: put an ImageView instead of ImageButton and handle ImageView's click events.
Edit: Please find a link to the project on my Github.
use gridView.setOnItemClickListener(.....) and to your root view add below line
android:descendantFocusability="blocksDescendants"
The ViewGroup will block its descendants from receiving focus.
Try to add
android:focusable="false"
android:focusableInTouchMode="false"
in your GridCell -->TextView
Try using recycler view if you are comfortable with it.
It doesn't gives any such problem in addition to this it has its own advantages.
Follow the link for complete explanation.
If you have any focus-able view in you your row layout, then the onItemClickListener will not be called. For this problem you need to customize your getView code and set onClickListener() on convertView and pass the callback to activity using the Interface. I have updated the code of your Adapter as below. Now you need to implement the GridViewItemClickListener on your activity and pass the instance while creating the Adapter instance.
public class MyGridViewAdapter extends BaseAdapter {
private Context mContext;
private final String[] mValues;
private GridViewItemClickListener mListener;
public MyGridViewAdapter(String[] values, Context context,GridViewItemClickListener listener ) {
mValues = values;
mContext = context;
mListener = listener;
}
#Override
public int getCount() {
return mValues.length;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridViewItem;
if (convertView == null) {
gridViewItem = new View(mContext);
gridViewItem = layoutInflater.inflate(R.layout.grid_cell, null);
TextView textView = (TextView)gridViewItem.findViewById(R.id.grid_item_number);
textView.setText(mValues[position]);
EditText editText = (EditText)gridViewItem.findViewById(R.id.grid_item_label);
} else {
gridViewItem = (View) convertView;
}
gridViewItem.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
Log.e("GRID", "onLongClick: " );
return true;
}
});
//Add an OnclickListener here
gridViewItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mListener != null){
mListener.onGridItemClick(v, position);
}
}
});
return gridViewItem;
}
public interface GridViewItemClickListener{
void onGridItemClick(View v, int index);
}
}
You can user click listeners inside the adapter it will work ,it should work like this
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridView;
MyObject obj = myObjects.get(position);
if (convertView == null) {
gridView = inflater.inflate(R.layout.grid_cell, null);
String textColour = "#000000";
TextView textView = (TextView) gridView.findViewById(R.id.grid_item_label);
textView.setText(Html.fromHtml(String.format("<font color='%s'>%s</font>", textColour, obj.getValue())));
TextView superScriptTv = (TextView) gridView.findViewById(R.id.grid_item_number);
superScriptTv.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// here you can use every item of grid acc to position
}
});
if (obj.getNumber() > 0) {
superScriptTv.setText(Html.fromHtml(String.format("<font>%s</font>", cell.getNumber())));
}
} else {
gridView = convertView;
}
gridView.setBackgroundColor(obj.getBackgroundColour());
return gridView;
}
how can the click listener work if you set the root element in GridCell.java as non-clickable ?
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:padding="0dp" android:layout_margin="0dp"
android:focusable="false"
android:clickable="false"
android:focusableInTouchMode="false"
Remove those lines from each of your components in the GridCell.java
android:focusable="false"
android:clickable="false"
android:focusableInTouchMode="false"
I don't think this is required for GridView, but sometimes for RecyclerView it is required to have android:clickable="true" on the root componenent of GridCell.java

How to implement list view with two parallel imageview in a row

Well I do not know what should be the proper title for the question , but my problem is quite amazing, do not know is it possible or not. Here is my question
I have series of images and I want to set them in a ListView. following is a ListView row Xml.(named anim_list_row)
<?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"
android:weightSum="100"
>
<ImageView
android:layout_width="0dp"
android:layout_height="350dp"
android:scaleType="fitXY"
android:id="#+id/iv_dummy_left"
android:layout_marginLeft="5dp"
android:layout_weight="50"/>
<ImageView
android:layout_width="0dp"
android:layout_height="350dp"
android:scaleType="fitXY"
android:id="#+id/iv_dummy_right"
android:layout_weight="50"
android:layout_marginRight="5dp"/>
</LinearLayout>
in this you can see that I want to set the 2 different images in two different let say left and right ImageView. Following is my adapter class
public class MListAdapter extends BaseAdapter {
private Context context;
private ArrayList<AnimListItems> mAnimListItems;
public MListAdapter(Context context, ArrayList<AnimListItems> mAnimListItems){
this.context = context;
this.mAnimListItems = mAnimListItems;
}
#Override
public int getCount() {
return mAnimListItems.size();
}
#Override
public Object getItem(int position) {
return navDrawerItems.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater mInflater = (LayoutInflater)
context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.anim_list_row, null);
}
ImageView imgIconLeft = (ImageView) convertView.findViewById(R.id.iv_dummy_left);
ImageView imgIconRight = (ImageView) convertView.findViewById(R.id.iv_dummy_right);
//TextView txtTitle = (TextView) convertView.findViewById(R.id.title);
imgIconLeft.setImageResource(navDrawerItems.get(position).getIcon());
//if I do not do +1 here it sets same image to both left and right ImageView
imgIconRight.setImageResource(navDrawerItems.get(position+1).getIcon());
// txtTitle.setText(navDrawerItems.get(position).getTitle());
return convertView;
}
}
so here is problem this list view is working but it is assigning the same images to both ImageView in the row. and if I do +1 as following
imgIconRight.setImageResource(navDrawerItems.get(position+1).getIcon())
then it helps in changing the image view at right side in the row, but the 2nd row repeat the image in its first imageview (I mean the image in the left ImageView of the 2nd row is same as the image in right ImageView of first row.)
So what is a solution of
Repeating images in a rows.
And How can I get each ImageView id and its resourceid of the image so that I can come to know which image has been clicked. And then I can able to set that image into another activity's ImageView. I mean I wanted to know which image has been clicked by the user , so I want to set same image in the ImageView of other activity.
Hello If you want to user one single array then i have made one demo example for your problem quickly i think it will help you.
MainActivity.java
public class MainActivity extends ActionBarActivity {
Item item;
ArrayList<Object> obj = new ArrayList<Object>();
MListAdapter adapter;
ListView lv;
int[] arrEnabledImageIds = new int[] { R.drawable.ic_launcher,
R.drawable.ic_delete_icon, R.drawable.ic_delete_icon,
R.drawable.ic_launcher, R.drawable.ic_delete_icon,
R.drawable.ic_launcher };
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.listView1);
for (int i = 0; i < arrEnabledImageIds.length; i++) {
Item itemInfo = new Item();
itemInfo.image1 = arrEnabledImageIds[i];
i++;
itemInfo.image2 = arrEnabledImageIds[i];
obj.add(itemInfo);
}
adapter = new MListAdapter(this, R.layout.row, obj);
lv.setAdapter(adapter);
}
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<ListView
android:id="#+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
Item.java
public class Item implements Serializable {
public static final long serialVersionUID = 1L;
public int image1;
public int image2;
}
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" >
<ImageView
android:id="#+id/ivLeft"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_launcher" />
<ImageView
android:id="#+id/ivRight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_launcher" />
</LinearLayout>
MListAdapter.java
public class MListAdapter extends ArrayAdapter<Object> {
private Context context;
int resId;
private ArrayList<Object> mAnimListItems;
public MListAdapter(Context context, int textViewResourceId,
ArrayList<Object> mAnimListItems) {
super(context, textViewResourceId, mAnimListItems);
this.resId = textViewResourceId;
this.context = context;
this.mAnimListItems = mAnimListItems;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(resId, null);
}
ImageView imgIconLeft = (ImageView) convertView
.findViewById(R.id.ivLeft);
ImageView imgIconRight = (ImageView) convertView
.findViewById(R.id.ivRight);
// TextView txtTitle = (TextView) convertView.findViewById(R.id.title);
Item item = (Item) mAnimListItems.get(position);
imgIconLeft.setImageResource(item.image1);
// if I do not do +1 here it sets same image to both left and right
// ImageView
imgIconRight.setImageResource(item.image2);
// txtTitle.setText(navDrawerItems.get(position).getTitle());
return convertView;
}
}
try to use two different array/arraylist to store left and rightside images seprately.
settag as l+position for left image
settag as r+position for right image
you can identify the clicked image by
imgIconLeft.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(v.getTag.toString().contains("l"){
// then it's a left button.
String position=v.getTag.toString().subString(1,v.getTag.toString().length()-1);
// to get position
}
});

Custom Gridview in fragment not populating

I'm trying to create a custom gridview inside a fragment that should look something like this:
http://imgur.com/6fEFYTN
So I created a FragmentLayout that contains the image and the label:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:id="#+id/grid_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
/>
<TextView
android:id="#+id/grid_label"
android:layout_width="fill_parent"
android:layout_height="45dp"
android:layout_marginTop="175dp"
android:background="#drawable/label"
android:gravity="center"
android:textColor="#FFFFFF"
android:textSize="12sp"
android:textStyle="bold" />
The adapter that manages the FragmentLayout looks like this:
public class CustomGridAdapter extends BaseAdapter{
private Context mContext;
private final String[] label;
private final int[] imgId;
public CustomGridAdapter(Context c,String[] label,int[] imgId ) {
mContext = c;
this.imgId = imgId;
this.label = label;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return 0;
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View grid;
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
grid = new View(mContext);
grid = inflater.inflate(R.layout.image_button_layout, null);
TextView textView = (TextView) grid.findViewById(R.id.grid_label);
ImageView imageView = (ImageView)grid.findViewById(R.id.grid_image);
textView.setText(label[position]);
imageView.setImageResource(imgId[position]);
} else {
grid = (View) convertView;
}
return grid;
}
}
The fragment grid is as follows:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<GridView
android:numColumns="auto_fit"
android:gravity="center"
android:columnWidth="90dp"
android:stretchMode="columnWidth"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/form_grid"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
/>
</LinearLayout>
I'm creating this from the onCreateView method, I'm using onclickListener so the images work as buttons and display a toast when pressed:
#Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_layout_softdrinks, container, false);
GridView grid = (GridView) rootView.findViewById(R.id.form_grid);
CustomGridAdapter adapter = new CustomGridAdapter(rootView.getContext(), label, imgId); //label and imgId are arrays containing strings and int respectively
grid.setAdapter(adapter);
grid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(inflater.getContext(), "You Clicked at " +label[+ position], Toast.LENGTH_SHORT).show();
}
});
return rootView;
}
The problem is that when I run the code, the screen is blank, so the gridview is not being populated.
Any advice on this?
First of all you will need to provide a payload in imgId array and label array.
Then your grid view won't inflate as well because you are returning 0 in your getCount method!
To inflate your layout replace in your getCount method
Return 0;
With
Return imgId.length;
The getCount method tells the base adapter how much images or strings(..data) you have in your array which you want to inflate in the grid view. If you returning 0, base adapter thinks that there are 0 data to inflate.

How to make grid-view horizontally scrollable in android

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.

Horizontal scrolling in android gridview

I have a grid view in my application and i need to scroll it horizontally.I have tried changing the gridview to gallery.But then only one row is available,but i need different rows as in a grid view.So basically what i need is a gridview that can be scrolled horizontally.Is there any efficient way to do this?Thanks in advance.
Regards
Anu
Hi,Thanks for the reply.i have tried using a Gallery and implement an adapter that provides a multirow view in its getView method.
My java file is:
public class Gridview extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Gallery g = (Gallery) findViewById(R.id.gallery);
g.setAdapter(new GridAdapter(this));
g.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id) {
Toast.makeText(Gridview.this, "" + position, Toast.LENGTH_SHORT).show();
}
});
}
public class GridAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
private Integer[] mImageIds = {
R.drawable.icon,
R.drawable.icon,
R.drawable.icon,
R.drawable.icon,
R.drawable.icon,
R.drawable.icon,
R.drawable.icon,
};
public GridAdapter(Context c) {
mContext = c;
TypedArray a = obtainStyledAttributes(R.styleable.HelloGallery);
mGalleryItemBackground = a.getResourceId(
R.styleable.HelloGallery_android_galleryItemBackground, 0);
a.recycle();
}
public int getCount() {
return mImageIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View v;
if(convertView==null)
{
LayoutInflater li = getLayoutInflater();
v = li.inflate(R.layout.icon, null);
ImageView iv = (ImageView)v.findViewById(R.id.icon_image);
iv.setImageResource(R.drawable.icon);
}
else
{
v = convertView;
}
return v;
}
}
}
main.xml is :
<?xml version="1.0" encoding="utf-8"?>
<Gallery xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gallery"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
icon.xml is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linearlayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ImageView
android:id="#+id/icon_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
</ImageView>
</LinearLayout>
The output i got is : http://www.4shared.com/photo/MzUcmzel/device.html
But this is not i need actually.i want the icons in different rows.Any help is appreciated.
I think your best bet is to use a Gallery and implement an adapter that provides a multirow view in its getView method. See Hello Gallery and look at the ImageAdapter implementation within.
Instead of the ImageView that getView returns in that example, you can, for example, inflate your own custom layout, for example a LinearLayout with vertical orientation.
You might consider a TableLayout inside a HorizontalScrollView, but the disadvantage there is that everything will be in memory at once, making it difficult to scale to lots of items. The Gallery recycles Views and offers some resource advantages.
I have already posted this answer here and here, but these questions are
identical...
There is a nice solution in Android from now on : 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);
}
True about using a Gallery or ListView re: re-using views. But if your list is not too long, you can try a TableLayout with a ViewFlipper. Here's a summary of possible options/solutions.
This post might get help you out what you wanted to achieve
Scroll like Shelf View
how about using a viewPager :
http://developer.android.com/reference/android/support/v4/view/ViewPager.html
?
Try to wrap it in HorizontalScrollView

Categories

Resources