How to add Imageview and Textview on Image? - android

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

Related

Change ImageView in a GridView Programmatically

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?

Dynamic Grid Layout

I want to implement grid, which will be populated dynamically. I want to know what is the best approach to implement this Relative layout(List View) or Grid Layout?
You can generate a GridView dynamically.
GridView would contain of ImageView and TextView as per your need. You will have to use your custom adapter. In it's getView method, populate the ImageView and TextView.
Example:
GridView item.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/imgItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="#drawable/ic_launcher" />
<TextView
android:id="#+id/txtItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="trebuchet"
android:textColor="#android:color/black"
android:textSize="15sp"
android:textStyle="bold" />
</LinearLayout>
Java code:
A POJO class for item:
public class Item
{
String title;
Drawable image;
//getter setter
}
Adapter class:
//getView method in your adapter class
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
View itemView = convertView;
ViewHolder holder = null;
if (itemView == null)
{
final LayoutInflater layoutInflater =
(LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
itemView = layoutInflater.inflate(resourceId, parent, false);
holder = new ViewHolder();
holder.imgItem = (ImageView) itemView.findViewById(R.id.imgItem);
holder.txtItem = (TextView) itemView.findViewById(R.id.txtItem);
itemView.setTag(holder);
}
else
{
holder = (ViewHolder) itemView.getTag();
}
Item item = getItem(position);
holder.imgItem.setImageDrawable(item.getImage());
holder.txtItem.setText(item.getTitle());
return itemView;
}
Now add adapter data in your Activity class and then set that adapter to GridView.
Refer to this and this
Hope it helps.
Simply use GridView with a custom adapter. Each time you want the view to update, call notifyDataSetChanged() on the adapter.
You want GridView. Easy example here. In your case, you will need to make an XML layout for each row to accommodate both your TextView and ImageView. Other answers here address that.

ListView items drawn on top of each other when scrolling (Android)

In a fragment, I have a ListView that has a custom ParseQueryAdapter<T>. The problem may not have anything to do with Parse, although I'm not sure.
As I was testing my app, I noticed something very strange. When I would scroll down my ListView, all the visible ListView items would be drawn on top of the next ListView item as seen in the second image below.
The list initialized properly as such:
As you can see, in my list item layout, I have an ImageView (ParseImageView to be specific) and a TextView. The TextView now displays some notes (don't mind the ID user_name_text_view) and the ImageView displays a placeholder blank profile picture.
When I scrolled down, the list looked like:
Here's my list view layout named fragment_post_view_list_view:
<?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="vertical" >
<ListView
android:id="#+id/post_list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
Here's my list item layout named list_item_post_view:
<?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">
<com.parse.ParseImageView
android:id="#+id/icon"
android:layout_width="75dp"
android:layout_height="75dp"
android:layout_alignParentLeft="true"
android:background="#drawable/com_facebook_profile_picture_blank_square" />
<TextView
android:id="#+id/user_name_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/icon"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#color/link_blue" />
</RelativeLayout>
Here's my adapter named PostViewListViewAdapter:
public class PostViewListViewAdapter extends ParseQueryAdapter<Post> {
// call superclass with a query to populate list view
public PostViewListViewAdapter(Context context, final String[] postsObjectIds) {
super(context, new ParseQueryAdapter.QueryFactory<Post>(){
public ParseQuery<Post> create() {
ParseQuery<Post> query = Post.getQuery();
query.whereContainedIn("objectId", Arrays.asList(postsObjectIds));
return query;
}
});
}
// this is similar to getView method in an adapter
#Override
public View getItemView(Post post, View v, ViewGroup parent) {
if(v == null) {
v = View.inflate(getContext(), R.layout.list_item_post_view, null);
}
super.getItemView(post, v, parent);
TextView usernameTextView = (TextView) v.findViewById(R.id.user_name_text_view);
usernameTextView.setText(post.getNotes()); // some string
return v;
}
}
How can I fix this problem?
Is this an issue with XML or Java?
I was following the two tutorials from Parse and the example from the Parse docs:
MealSpotting
Parse Query Adapter
I set the adapter and ListView here:
View rootView = inflater.inflate(R.layout.fragment_post_view_list_view, container, false);
mPostsObjectIds = SOME_STRING[];
PostViewListViewAdapter adapter = new PostViewListViewAdapter(getActivity(), mPostsObjectIds);
ListView listView = (ListView) rootView.findViewById(R.id.post_list_view);
listView.setAdapter(adapter);
I've tried getting rid of the ParseImageView in my list item layout, but my TextViews still draw on top of each other when I scroll.
Edit:
I forgot to mention that the list items display on top of each other after an orientation change.
I tested this on my Galaxy S5 (Android version 4.4.2 and Parse 1.4.1).
In my Activity, I show the Fragment here (called PostViewListViewFragment):
getSupportFragmentManager().beginTransaction().add(android.R.id.content, new PostViewListViewFragment()).commit();
Try below 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="match_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/post_list_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="none" >
</ListView>
</RelativeLayout >
Make Sure your adapter like this:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
// reuse views
if (rowView == null) {
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.rowlayout, null);
// configure view holder
ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) rowView.findViewById(R.id.TextView01);
rowView.setTag(viewHolder);
}
// fill data
ViewHolder holder = (ViewHolder) rowView.getTag();
String s = names[position];
holder.text.setText(s);
return rowView;
}
}
PS:You should watch this Google IO video about Listview,and here is the slides.
First create a ViewHolder class
static class ViewHolder {
protected TextView usernameTextView;
}
Then change your getItemView method like below
public View getItemView (Post post, View convertView , ViewGroup parent)
{
ViewHolder viewHolder = null;
if (convertView == null)
{
LayoutInflater inflator = context.getLayoutInflater();
convertView = inflator.inflate(R.layout.list_item_post_view, null);
viewHolder = new ViewHolder();
viewHolder.usernameTextView = (TextView)convertView.findViewById(R.id.user_name_text_view);
convertView.setTag(viewHolder);
convertView.setTag(R.id.user_name_text_view, viewHolder.usernameTextView);
}
else
{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.usernameTextView.setText(post.getNotes()); // some string
return convertView;
}
The problem seems to be in your list item layout -
Change it to this -
<?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">
<com.parse.ParseImageView
android:id="#+id/icon"
android:layout_width="75dp"
android:layout_height="75dp"
android:layout_alignParentLeft="true" />
<TextView
android:id="#+id/user_name_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/icon"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#color/link_blue" />
</RelativeLayout>
Probably you have extra background for each list item set that is causing such effect.
Alter and watch.
Hope this gives you idea!
Try changing your list view layout height to match_parent.
Credit to #VedPrakash for helping me fix this.
In case it helps anyone, I fixed the problem by replacing the fragment not adding it. So I changed this line from:
getSupportFragmentManager().beginTransaction().add(android.R.id.content, new PostViewListViewFragment()).commit();
to:
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, new PostViewListViewFragment()).commit();

Android custom ListView items (findViewById returns null)

I'm trying to populate custom ListView with this LazyAdapter class from this tutorial
I want to make list view items with custom design. Layout file list_row.xml is in my layouts file just like in the tutorial. This is a slightly modified getView function in LazyAdapter class:
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
//vi = inflater.inflate(R.layout.list_row, null); //EDITED
vi = inflater.inflate(R.layout.list_row, parent, false);
TextView title = (TextView)vi.findViewById(R.id.title); // title
TextView subtitle = (TextView)vi.findViewById(R.id.subtitle); // artist name
//ImageView thumb_image=(ImageView)vi.findViewById(R.id.list_image);
//This is not needed
//HashMap<String, String> post = new HashMap<String, String>();
HashMap<String, String> post;
post = data.get(position);
// Setting all values in listview
title.setText(post.get("title")); //the code crashes here
subtitle.setText(post.get("subtitle"));
//imageLoader.DisplayImage(song.get(CustomizedListView.KEY_THUMB_URL), thumb_image);
return vi;
}
Well this code crashes at title.setText(), because the title is null. I read somewhere that this makes sense because this LazyAdapter is calling findViewById before setContentView or something..
So how do I have to do this? And how does this code work for that guy?
Update
This is the list_row.xml file:
<?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:background="#drawable/list_selector"
android:orientation="horizontal"
android:padding="5dip" >
<!-- Title -->
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#040404"
android:typeface="sans"
android:textSize="14sp"
android:textStyle="bold"/>
<!-- Subtitle -->
<TextView
android:id="#+id/subtitle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#id/subtitle"
android:textColor="#343434"
android:textSize="10sp"
android:layout_marginTop="1dip" />
</RelativeLayout>
To save space I'm only adding ListView xml from the main activity layout file:
<ListView
android:id="#+id/feedListView"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/volumeControl1">
</ListView>
Adapter code: http://pastebin.com/niC1yXiJ
And the stack trace: http://pastebin.com/myW8B0Xz
Try passing in the parent when you inflate your cell. Using this method:
public View inflate (int resource, ViewGroup root, boolean attachToRoot)
vi = inflater.inflate(R.layout.list_row, parent, false);
This was a hell of a ride (two sleepless nights). Thanks for all your help, somehow I fixed it! :)
Mostly thanks to this question Null pointer exception in getView() of custom Adapter I made new getView function:
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = new ViewHolder();
View vi = convertView;
if (vi == null) {
LayoutInflater inflater = ((Activity)activity).getLayoutInflater();
vi = inflater.inflate(R.layout.list_row, null);
holder.title = (TextView) vi.findViewById(R.id.title);
holder.subtitle = (TextView) vi.findViewById(R.id.subtitle);
vi.setTag(holder);
} else {
holder = (ViewHolder) vi.getTag();
}
HashMap<String, String> post;
post = data.get(position);
holder.title.setText(post.get("title"));
holder.subtitle.setText(post.get("subtitle"));
return vi;
}
holder is just a simple class:
private class ViewHolder {
public TextView title;
public TextView subtitle;
}
I've done that and I also copied xml drawable files in all drawable folders (merged all). So one of this actions fixed it, but I'm not quite sure what..
If you get android.widget.AbsListView.obtainView(AbsListView.java:1408) exception than your returned View of getView() is probably null.So check first of all that you are not return null view.

Overlay onto a gridview

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.

Categories

Resources