I have a gridview I created using this tutorial GridView Android, which works just fine. Now I'd like to overlay an image onto the item of the gridview if say the item is clicked. I'm not sure how to do this, whether I use another gridview and merge them or just have lots of image views :s. Just to clarify the question: How do I overlay onto gridview items? Thanks in advance!
So there are a few ways you might achieve this but possibly the most flexible would be to use a custom view in the getView method.
Add a LayoutInflater to your ImageAdapter class:
private LayoutInflater mInflater;
Initialize it in the constructor:
public ImageAdapter(Context c) {
mContext = c;
// Initialise the inflater
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
This is used to inflate an xml view such as this:
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:id="#+id/mainImage"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
<ImageView
android:id="#+id/overlayImage"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:visibility="gone"
/>
</RelativeLayout>
Inflate this view in the ImageAdapter class getView method
public View getView(int position, View convertView, ViewGroup parent) {
// RelativeLayout as used in the xml view
RelativeLayout customView;
if (convertView == null) { // if it's not recycled, inflate
customView = (RelativeLayout) mInflater.inflate(R.layout.customview, null);
} else {
imageView = (RelativeLayout) convertView;
}
// Get the mainImageView from the parent
ImageView mainImage = (ImageView) customView.findViewById(R.id.mainImage);
imageView.setImageResource(mThumbIds[position]);
// Overlay view
ImageView overlayImage = (ImageView) customView.findViewById(R.id.overlayImage);
overlayImage.setImageResource(mOverlayThumbIds[position]); // new array containing overlay references
return customView;
}
Then show the overlay image on click
gridview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
ImageView overlayImage = (ImageView) v.findViewById(R.id.overlayImage);
overlayImage.setVisibility(View.VISIBLE);
}
});
This is a very basic example but hopefully you will find the approach useful.
Related
I'm trying to bind a custom layout (a LinearLayout containing two TextViews) to a Spinner. I subclassed ArrayAdapter (mostly) correctly. Selecting an item in the Spinner calls getView() correctly, setting the LinearLayout's TextViews' values correctly. The problem is the initial display of the items in the Spinner (when clicking on the Spinner) just shows Objects; not the TextViews they should be displaying. Only AFTER clicking on one of the Objects does the Spinner correctly set the TextViews using my custom adapter's getView() method. Here's the custom adapter class:
public class BusRouteAdapter extends ArrayAdapter<BusRoute> {
...
public BusRouteAdapter(Context context, int resource, int textViewId, ArrayList<BusRoute> routes) {
super(context, resource, textViewId, routes);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
BusRoute route = getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.bus_route, parent, false);
}
TextView tvBusRoute = (TextView) convertView.findViewById(R.id.tvBusRoute);
TextView tvBusRouteNumber = (TextView) convertView.findViewById(R.id.tvBusRouteNumber);
tvBusRoute.setText(route.routeName);
tvBusRoute.setTag(route.route);
tvBusRouteNumber.setText(route.route);
if (!route.routeColor.equals("")) {
tvBusRouteNumber.setBackgroundColor(Color.parseColor(route.routeColor));
}
return convertView;
}
}
Here's the layout that is to be used for each Spinner list item (bus_route.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="1">
<TextView
android:id="#+id/tvBusRouteNumber"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.25"
android:padding="8dp" />
<TextView
android:id="#+id/tvBusRoute"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.75"
android:padding="8dp" />
</LinearLayout>
And in my Activity, I'm setting the adapter to a properly-populated list of BusRoute objects:
busRouteAdapter = new BusRouteAdapter(getBaseContext(), R.layout.bus_route, R.id.tvBusRoute, arrayOfBusRoutes);
routesSpinner.setAdapter(busRouteAdapter);
It does seem strange that I need to pass the Layout id (R.layout.bus_route) AND one of the TextViews contained in that Layout (R.id.tvBusRoute).
Here's what is rendered when clicking on the Spinner:
But if I click one of the Objects, getView() is called, and the selected Layout and TextViews are rendered properly (apparently I selected "GMU - Pentagon"):
What am I missing to get the Spinner's popup list to display ALL my bus route items rendered correctly?
I think you need to override getDropDownView to deal with spinners
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
BusRoute route = getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.bus_route, parent, false);
}
TextView tvBusRoute = (TextView) convertView.findViewById(R.id.tvBusRoute);
TextView tvBusRouteNumber = (TextView) convertView.findViewById(R.id.tvBusRouteNumber);
tvBusRoute.setText(route.routeName);
tvBusRoute.setTag(route.route);
tvBusRouteNumber.setText(route.route);
if (!route.routeColor.equals("")) {
tvBusRouteNumber.setBackgroundColor(Color.parseColor(route.routeColor));
}
return convertView;
}
I am using ListFragment and ArrayAdapter to show a Image view list using following list_view.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/img"
android:layout_width="match_parent"
android:layout_height="200dp"/>
In my Adapter.getview I am using picasso to load the image:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (null == convertView) {
convertView = inflater.inflate(R.layout.list_view, parent, false);
}
Picasso
.with(context)
.load("http://i.imgur.com/rFLNqWI.jpg")
.fit()
.into((ImageView) convertView);
return convertView;
}
This is onActivityCreated method in Fragment class extended by ListFragment:
TestAdapter adapt = new TestAdapter(getActivity().getApplicationContext(), R.layout.list_view, pictures);
setListAdapter(adapt);
Above code is giving me a listview where I can see the images loading from picasso library. How can I add text and image on the image loaded by picasso in listview? Inshort like this:
You can see one text "Type text here" in left bottom corner and one icon on right top corner (not exactly in the corner)
You could implement a Picasso Transformation where you take the bitmap and then use the Canvas primitives to draw/render the text on top of the Bitmap and return the final bitmap.
Another approach would be to use a RelativeLayout with 3 sub-views: an ImageView which stretches to its parent (the RelativeLayout) so it becomes the overall background; and then a TextView for your text and finally another ImageView for your icon.
Create list_view.xml like this
<Relative layout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/img"
android:layout_width="match_parent"
android:layout_height="200dp"/>
<EditText
android:layout_width="wrap_content"
android:layout_alignParentLeft="true"
android:text="Type your text"
android:layout_alignParentBottom="true"
android:layout_margin="20dp"
android:layout_height="200dp"/>
</Relative>
you can use ViewHolder to set TextView and image both, and then use it with picasso.
Here's the code snippet.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ViewHolder holder;
if (row == null) {
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ViewHolder();
holder.titleTextView = (TextView) row.findViewById(R.id.grid_item_title);
holder.imageView = (ImageView) row.findViewById(R.id.grid_item_image);
row.setTag(holder);
} else {
holder = (ViewHolder) row.getTag();
}
GridItem item = mGridData.get(position);
holder.titleTextView.setText(Html.fromHtml(item.getTitle()));
Picasso.with(mContext).load(item.getImage()).into(holder.imageView);
return row;
}
For more details refer
http://javatechig.com/android/download-and-display-image-in-android-gridview
I've set up a grid of ImageViews with TextView overlays. My ImageAdapter code is as follows:
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
View grid;
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
grid = new View(mContext);
grid = inflater.inflate(R.layout.image, null);
TextView textView = (TextView)grid.findViewById(R.id.mastery_text);
imageView = (ImageView)grid.findViewById(R.id.mastery_image);
grid.setLayoutParams(new GridView.LayoutParams(150, 150));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
grid.setPadding(8, 8, 8, 8);
grid.setBackgroundResource(R.color.orange);
imageView.setImageResource(mThumbIds[position]);
} else {
grid = (View) convertView;
}
return grid;
}
The corresponding XML layout for my ImageAdapter is this:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_practitioner"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/mastery_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="bottom"
android:background="#bbffffff"
android:focusable="false"
android:focusableInTouchMode="false" >
<TextView android:id="#+id/mastery_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:textColor="#color/black"
android:gravity="bottom|center"
android:textSize="12sp"
android:textAllCaps="true"
android:paddingBottom="0dp"
android:text="3/3"
/>
</LinearLayout>
</FrameLayout>
XML code for my GridView (activity class):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:id="#+id/gridview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="4"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:gravity="center" />
</LinearLayout>
Here is the onCreate method of my main activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_masteries);
GridView gridview = (GridView) findViewById(R.id.gridview);
ImageAdapter adapter = new ImageAdapter(this);
gridview.setAdapter(adapter);
gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
Toast.makeText(Masteries.this, "" + position,
Toast.LENGTH_SHORT).show();
}
});
}
I want to, after initializing the grid with the images, change one of the ImageViews from my activity class, given its position on the grid. How would I do that?
I'm not asking to change the image in response to an onItemClick.
Thanks in advance!
Edit:
I'm thinking of creating a changeImage(int position, int imageId) method in my Adapter and calling that from my activity class. Is that the right approach?
In your adapter:
public void updateImage(int position, int resourceId)
{
mThumbIds[position] = resourceId;
notifyDataSetChanged();
}
In your activity:
mAdapter.updateImage(<position>, <image_resource_id>);
Notes
You will have to make the adapter a member of your activity
The main idea is that you modify the backing data and and notify the GridView that this has changed and it is time to be redrawn
Your getView() method implementation needs a lot of improvement. It will cause lots of bugs once the system starts recycling the views (the convertView parameter comes in != null for a position different than it was used for last time)
Here's a sketch of how your getView() should look like:
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder viewHolder;
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = inflater.inflate(R.layout.image, parent, false);
// next three lines would not be necessary if:
// a) it is the same for every item;
// b) you inflate properly (using the parent);
// c) you specify this in the item's xml (R.layout.image)
convertView.setLayoutParams(new GridView.LayoutParams(150, 150));
convertView.setPadding(8, 8, 8, 8);
convertView.setBackgroundResource(android.R.color.holo_red_light);
viewHolder = new ViewHolder();
viewHolder.mTextView = (TextView)convertView.findViewById(R.id.mastery_text);
viewHolder.mImageView = (ImageView)convertView.findViewById(R.id.mastery_image);
// this could also be set in xml perhaps
viewHolder.mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder)convertView.getTag();
}
// update the values every time we are being asked to update the item,
// because the item might have been reused from a different position
viewHolder.mImageView.setImageResource(mThumbIds[position]);
//viewHolder.mTextView.setText("myText");
return convertView;
}
public static class ViewHolder
{
TextView mTextView;
ImageView mImageView;
}
You can set a unique id to each ImageView using names (See here) or even integer numbers with a sequence or something (increasing at each image you put in the view).
Another good way to do this is using the tags, with setTag() and getTag().
This question has a good answer: What is the main purpose of setTag() getTag() methods of View?
I'm trying to create a horizontal scroll view inside a listView. My main activity uses xml containing listview. It calls a custom adapter which extends a base adapter. This custom adapter inflates a xml containing HorizontalListview and getView method calls another adapter.
THis is my custom Adapter that inflates a xml containing a TextView and a HorizontalListView. I call an adapter for the HorizontalListView inside the getView, in which i pass in my activity, and I also pass in the array of items. When I run my application the customAdapter works fine and I get the right views, but my HorizontalListView doesn't show up at all. I don't think I'm passing in the right parameters. I thought passing the activity would be good, but I guess not.
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
LinearLayout lg = (LinearLayout) convertView;
if(lg == null) {
lg = (LinearLayout)firstInflator.inflate(R.layout.second_layout,null);
holder = new ViewHolder();
holder.hlv1 = (HorizontalListView)lg.findViewById(R.id.listview);
lg.setTag(holder);
}
else {
holder = (ViewHolder)lg.getTag();
}
mVideos = dA.mShows.get(categories[position]);
holder.hlv1.setAdapter(new HorizontalGalleryAdapter(dA, mVideos));
((TextView) lg.getChildAt(0)).setText(categories[position]);
return lg;
}
THis is my HorizontalGalleryAdapter. My problem is that only the first adapter is working properly.
private final LayoutInflater mInflator;
private ArrayList<Video> mVideos;
private final ImageDownloader mDownload = new ImageDownloader();
public HorizontalGalleryAdapter(DataActivity da, ArrayList<Video>mVideos){
mInflator = da.getLayoutInflater();
this.mVideos = mVideos;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
LinearLayout lg = (LinearLayout)convertView;
if(lg == null) {
lg = (LinearLayout)mInflator.inflate(R.layout.third_layout,null);
}
imageView = (ImageView) lg.getChildAt(0);
mDownload.download(mVideos.get(position).mThumb.toString(), imageView);
((TextView) lg.getChildAt(1)).setText(mVideos.get(position).mTitle);
return lg;
}
This is my xml for the HorizontalListView
<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="#000000"
android:id="#+id/second">
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"/>
<com.devsmart.android.ui.HorizontalListView
android:id="#+id/listview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#808080">
</com.devsmart.android.ui.HorizontalListView>
</LinearLayout>
I am developing an app which has a listView having 1 textView which displays the content and one imageView. What i want is, when i click the listView i want to set the imageView with the tick mark image which i have. Its working fine. Once i click the listView, the tick mark image is loaded on that listview item on which i clicked.
The problem arises when i scroll. When i scroll, i could see some other listview item down below has a tick mark loaded. not sure how the image was set on that position.
I have read somewhere that when the listView is scrolled, the view is refreshed. Is that causing the problem?
Can anyone help how can iresolve this? I want the image to be shown(loaded) on the listView item on which i clicked and now other listView item.
Below is the xml stating listView items
method_item.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/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#android:color/white"
android:text="This is a check box button which reacts upon the check that user clicks. I am testing it with the big string and checking how it looks" />
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView1"
android:layout_centerHorizontal="true" />
<ImageView
android:id="#+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/imageView1"
android:layout_alignParentRight="true"
android:layout_marginRight="34dp" />
</RelativeLayout>
Below is the part of class snippet:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.method_list_main);
final ListView list = (ListView)findViewById(R.id.listView1);
adapter=new MethodLazyAdapter(this,ARRAY.preparationSteps,ARRAY.timeToPrepare,ARRAY.arrowValue,noOfSteps,list);
list.setAdapter(adapter);
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// TODO Auto-generated method stub
RelativeLayout ll = (RelativeLayout) view;
ImageView image = (ImageView)ll.findViewById(R.id.imageView2);
if(tick[position]){
tick[position] = false;
image.setImageResource(0);
}
else{
tick[position] = true;
image.setImageResource(R.drawable.select_right);
}
System.out.println("Position is: "+position);
}
});
}
Initially all tick[i] value is set to false.
Below is the getView function of adapter class
public View getView(final int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.method_item, null);
TextView text = (TextView)vi.findViewById(R.id.textView1);
text.setText(preparationSteps\[position\]);
return vi;
}
Try this to get what you want
in public area add this variable
public SparseBooleanArray checked = new SparseBooleanArray();
then in onItemClick
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
boolean stat = checked.get(position, false);
checked.put(position, !stat);
adapter.setChecked();
System.out.println("Position is: "+position);
}
});
and in Adapter Class
If adapter not sub class in activiy add variable in public area
private SparseBooleanArray checked = new SparseBooleanArray();
and add this method to class
public void setChecked(SparseBooleanArray ch){
checked = ch;
notifyDataSetChanged();
}
Or if it sub class use our cheked variable we defined it up
then in getView method
public View getView(final int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.method_item, null);
TextView text = (TextView)vi.findViewById(R.id.textView1);
text.setText(preparationSteps\[position\]);
ImageView image = (ImageView)vi.findViewById(R.id.imageView2);
if(checked.get(position, false)){
image.setImageResource(0);
}
else{
image.setImageResource(R.drawable.select_right);
}
return vi;
}
Please let me know if this help you.
Check out this post:
android - populating ListView with data from JSONArray
the reason for that is bacouse your are using your converted view wrong.
follow the example code on the post i paste.
if you will inflate your row view every time this problem will disappear. but this implementation is not recommended.