Fixing tiny images in GridView? - java

I'm trying to implement a basic GridView gallery as per the Android Developer Guide/Tutorial.
The ImageViews inside my grid are Bitmaps taken from a user's camera.
This works fine except for the fact that my images are incredibly small.
My xml:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gridview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnWidth="90dp"
android:numColumns="auto_fit"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:gravity="center"
/>
</LinearLayout>
My ImageAdapter
public class ImageAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<Bitmap> imgs;
public ImageAdapter(Context c, ArrayList<Bitmap> arrayList) {
mContext = c;
imgs = arrayList;
}
public int getCount() {
return imgs.size();
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
// if it's not recycled, initialize some attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageBitmap(imgs.get(position));
return imageView;
}
}
I've tried various things to fix this issue, but the only one that seems to work is adjusting the ImageView's layout params to enormous numbers (e.g. GridView.LayoutParams(300, 300)).
However, even if I do this, my images are still relatively small (i.e. nowhere near 300dp x 300dp).
Any idea what I'm doing wrong?

Put this param in your ImageView.
android:adjustViewBounds="true"
You can see this too.
How to find cell width from StaggeredGridLayoutManager?

Setting layout params in my adapter to GridView.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)) managed to fix the issue.
Found this solution at GridView items are too small - Android

Try to change for bigger size:
android:columnWidth="90dp"

you should accept the answer of
android:adjustViewBounds="true"
What it means?it stretches your image to fit the height and width of your image view so they won't be small,but why you don't want to use
android:ScaleType="fitXY"?
Because first option adjusted the proportion of your image so it won't lose the quality and second one anyway stretches it and it loses quality!
IMPORTANT:be aware that if image will be too small,adjust option will not work as it must save the image proportion,so its all up to you what you want to use!

The problem is that new GridView.LayoutParams() expect args in pixels.
So, your need to convert 85 from dp to pixels first.

Related

need an example trying to use svg/png

This is my first post...im a beginner trying to make an app for android.
im trying to make a simple match game using a deck of playing cards. Ive been able to get open source svg and png playing cards online. They either come in individual cards images (in png or svg formats) or one image (svg or png) with every card spaced nicely with a contrast background.
With all of the research ive done, i try to utilize these svg or png files but run into either out of memory issues or very slow UX performance.
My goal is to get a gridview to show all 52 cards that swipe horizontally. and if i click on a card, and match its face...then i get a point.
heres my layout activty_play_board.xml
just have one item...a gridview:
<GridView
android:id="#+id/gridView"
android:layout_width="match_parent"
android:layout_height="540dp"
android:horizontalSpacing="2dp"
android:numColumns="4"
android:stretchMode="columnWidth"
android:verticalSpacing="2dp" />
I use this public class that i got from googles dev website. it allows me to fill in the gridview with the svg or png cards
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
return mThumbIds.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
// if it's not recycled, initialize some attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(200, 270));
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
imageView.setPadding(4,4, 4, 4);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageResource(mThumbIds[position]);
return imageView;
}
private Integer[] mThumbIds = {
R.drawable.two_of_clubs,
R.drawable.two_of_diamonds,
R.drawable.two_of_hearts,
R.drawable.two_of_spades,
R.drawable.three_of_clubs,
R.drawable.three_of_diamonds,
R.drawable.three_of_hearts,
R.drawable.three_of_spades,
R.drawable.four_of_clubs,
R.drawable.four_of_diamonds,
R.drawable.four_of_hearts,
R.drawable.four_of_spades,
R.drawable.five_of_clubs,
R.drawable.five_of_diamonds,
R.drawable.five_of_hearts,
R.drawable.five_of_spades,
R.drawable.six_of_diamonds,
R.drawable.six_of_hearts,
R.drawable.six_of_spades,
R.drawable.six_of_clubs,
R.drawable.seven_of_diamonds,
R.drawable.seven_of_hearts,
R.drawable.seven_of_spades,
R.drawable.seven_of_clubs,
R.drawable.eight_of_diamonds,
R.drawable.eight_of_hearts,
R.drawable.eight_of_clubs,
R.drawable.eight_of_spades,
R.drawable.nine_of_diamonds,
R.drawable.nine_of_hearts,
R.drawable.nine_of_spades,
R.drawable.nine_of_clubs,
R.drawable.ten_of_clubs,
R.drawable.ten_of_diamonds,
R.drawable.ten_of_hearts,
R.drawable.ten_of_spades,
R.drawable.jack_of_clubs,
R.drawable.jack_of_diamonds,
R.drawable.jack_of_hearts,
R.drawable.jack_of_spades,
R.drawable.queen_of_clubs,
R.drawable.queen_of_diamonds,
R.drawable.queen_of_hearts,
R.drawable.queen_of_spades,
R.drawable.king_of_spades,
R.drawable.king_of_clubs,
R.drawable.king_of_diamonds,
R.drawable.king_of_hearts,
R.drawable.ace_of_spades,
R.drawable.ace_of_diamonds,
R.drawable.ace_of_hearts,
R.drawable.ace_of_clubs
};}
heres my onCreate:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_grid_board);
Button goBackOnClick = (Button) findViewById(R.id.playBoardButton);
GridView gridview = (GridView) findViewById(R.id.gridView);
gridview.setAdapter(new ImageAdapter(this));
gridview.setOnItemClickListener(newAdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
Toast.makeText(GridBoard.this, "Spot: " + position, Toast.LENGTH_LONG).show();
}
});
I have several questions.
How do i utilize the SVG file? am i calling the one big svg file and then referencing a specific location on the file when i call it for an imageview within my gridview?
i dont know how to use the one big SVG file, so ive tried using the individual svg images. but when i do that, my device is very laggy and slow. also sometimes the app crashes due to out of memory errors. Is there a special syntax to use when trying to reference a specific card within the large SVG file? Or do i have to manually edit the big svg file and get the smaller cards?
Is there a better way to do this than using a gridview?
any other general guidance would be greatly appreciated.
Thank you!
Heres my card sources:
one big palette
https://upload.wikimedia.org/wikipedia/commons/8/81/English_pattern_playing_cards_deck.svg
individual cards and one big palette
http://byronknoll.blogspot.com/2011/03/vector-playing-cards.html

Dynamically adding view or inflating layout to RecyclerView's item

I am working on a social network application in which I need to show feeds to subscribers.. for showing feeds in a list. I am using RecyclerView. No Problem till now... but the problem comes when I have to show some comments on the feed. I am trying to accomplish a layout similar to Instagram where they show an image and maximum 3-4 comments with it in the main list. I am getting Image links and its comments (in JSON array form) from server.. sometimes I get comment array size 0 and sometime 1/2../10. I have created an XML for the comment layout that contains 2 TextView and I am inflating it in FeedViewHolder based on my ViewType.. my item_comment look like
<RelativeLayout
android:id="#+id/comment_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="5dp"
android:paddingLeft="5dp"
android:paddingTop="5dp">
<TextView
android:textStyle="bold"
android:textColor="#color/indigo_500"
android:id="#+id/comment_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:src="#drawable/profile_pic"
android:text="Somesh Kumar"/>
<TextView
android:id="#+id/comment_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/comment_name"
android:ellipsize="end"
android:paddingLeft="5dp"
android:singleLine="true"
android:text="This is a comment"/>
</RelativeLayout>
I am passing my feed list to RecyclerView adaptor..and then I am checking if the item (that will be shown) should have the comments or not.
#Override
public int getItemViewType(int position)
{
FeedParser.DataClass dataClass = feedList.get(position);
int ITEM_TYPE = 0;
if (dataClass.getPost_type() == FEED_TYPE_PICTURE) // Feed item contains caption with pictures
{
// check if it has comments
if (dataClass.getComments().size() == 0)
{
ITEM_TYPE = PICTURE_WITHOUT_COMMENTS;
}
else
{
ITEM_TYPE = PICTURE_WITH_COMMENTS;
}
}
return ITEM_TYPE;
}
and passing ITEM_TYPE to onCreateViewHolder like
#Override
public FeedViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_feed, parent, false);
return new FeedViewHolder(itemView, viewType);
}
and in FeedViewHolder inflating item layout and comment layout if viewType has comments
public FeedViewHolder(View itemView, int viewType)
{
super(itemView);
tvFeedUsername = (TextView) itemView.findViewById(R.id.tvFeedUsername);
tvFeedCaption = (TextView) itemView.findViewById(R.id.tvFeedCaption);
switch (viewType)
{
// TODO: Write code for other feed type such as picture and video
// viewType 1 = PICTURE_WITH_COMMENTS
case 1:
layoutComments = (LinearLayout) itemView.findViewById(R.id.layoutComments);
commentView = layoutInflater.inflate(R.layout.item_comment, null);
postCommentText = (TextView) commentView.findViewById(R.id.comment_text);
postCommentName = (TextView) commentView.findViewById(R.id.comment_name);
layoutComments.addView(commentView);
break;
}
}
I have verified this works perfect but when i setText for holder.postCommentName & holder.postCommentText in onBindViewHolder it only set text for last comment ( i know it's because i am looping through all the comment and setting them one by one on the same holder.postCommentText and holder.postCommentName here is my onBindViewHolder..
#Override
public void onBindViewHolder(FeedViewHolder holder, int position)
{
FeedParser.DataClass feedModel = feedList.get(position);
holder.tvFeedUsername.setText(feedModel.getName());
holder.tvFeedCaption.setText(feedModel.getPost_status());
if (getItemViewType(position) == TEXT_WITH_COMMENTS)
{
for (int commentNum = 0; commentNum < feedModel.getComments().size(); commentNum++)
{
holder.postCommentName.setText(feedModel.getComments().get(commentNum).getUser_name());
holder.postCommentText.setText(feedModel.getComments().get(commentNum).getComment());
}
}
}
I don't know even if this is the right approach or not... but this is how some people wrote an answer here... like This one . I have searched many SO post but not getting what I want. Is there any other way where I can inflate comment's XML layout and add it multiple time on RecyclerView 's item?
Thanks any help would be much appreciated!
i Believe you need to create a nested recycler view in the main recycler view and you need to pass the data into the nested adapter as that of the comments .So basically
1.)Main Recycler View contains Caption , Image , RecyclerView for comments (as per instagram)
2.)In the second reyclerview put your above comment layout and create a seperate adapter with data as comments
Thats It .. Ask me for any further help

How to offset row margins of a GridView

I have a gridview full of images and the rows of a grid view align by columns like this
1_2_3
4_5_6
7_8_9
However I want to offset certain rows to get something like this
1_2_3_
_4_5_6
7_8_9_
So that the second row and an unknown number of additional rows are moved over to the right.
One solution is to make multiple gridviews and shift them over accordingly but that won't work when I have alot of rows. Another would be to somehow change the margins in the ImageAdapter using the position to get the row but I haven't been able to make that work without crashing. Is trying to edit the LayoutParams in the ImageAdapter even the right way to go about something like this?
You can use two types of views, with two layouts, for example:
in your adapter, you could implements:
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getItemViewType(int position) {
if (isImageLeft(position)) {
return VIEW_TYPE_LEFT_IMAGE; //TODO: you should define it
} else {
return VIEW_TYPE_RIGHT_IMAGE;//TODO: you should define it
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null){
if (getItemViewType(int position) == VIEW_TYPE_LEFT_IMAGE){
view = inflater.inflate(R.layout.layout_image_left, null);//TODO: you should have set the reference of LayoutInflater
}else{
view = inflater.inflate(R.layout.layout_image_right, null);
}
}
//.......
}
and in those two layout file, you could set a LinearLayout (or other layout as you like), with ImageView inside with the left, or right margin respectively. for example:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp" />
</LinearLayout>

Custom Array Adapter Returning Blank Screen?

I'm still very new to application development, so this is probably a very stupid question but I can't seem to find the right answer (or at least one that I can understand with my very limited knowledge of java).
I'm using a custom ArrayAdapter called ListRow. It works fine with a regular Activity, but not with the ListActivity that I need it to be in for my app to work.
Below is a sample of the code that I'm using. Any help would be greatly appreciated and you'd be helping a ton!
ListView mListview;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new ListRow(this, THEME_NAMES, THEME_ICONS));
getListView().setTextFilterEnabled(true);
}
public class ListRow extends BaseAdapter {
private Context mContext;
private String[] mThemeNames = THEME_NAMES;
private int[] mThemeIcons = THEME_ICONS;
public ListRow(Context c, String[] t, int[] i) {
mContext = c;
mThemeNames = t;
mThemeIcons = i;
mListview=(ListView)findViewById(R.id.list);
}
#Override
public int getCount() {
return mThemeNames.length;
}
#Override
public Object getItem(int arg0) {
return null;
}
#Override
public long getItemId(int arg0) {
return 0;
}
#Override
public View getView(int position, View converView, ViewGroup parent) {
View List;
if(converView==null){
List=new View(mContext);
LayoutInflater mLayoutinflater=getLayoutInflater();
List=mLayoutinflater.inflate(R.layout.list_view, parent, false);
} else {
List = (View)converView;
}
ImageView imageView = (ImageView)List.findViewById(R.id.image);
TextView textView = (TextView)List.findViewById(R.id.text);
imageView.setImageResource(mThemeIcons[position]);
textView.setText(mThemeNames[position]);
return List;
}
}
And here's the layout I've defined for each list item
<?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" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="center"
android:id="#+id/image"
android:layout_alignParentLeft="true"
android:contentDescription="#string/preview" />
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/image" />
</RelativeLayout>
If you can, please use small words with me lol, java has turned out to be hard to understand for me, and also try to explain as much as you can. Thanks in advance!
FIGURED IT OUT!
So I just put you all through a bit of hell. The layout that contains my list items is called list_item, not list_view. However I have learned a lot here so THANK YOU ALL VERY MUCH! I wish there were a way I could help you guys out...
Moral of this question? CHECK YOUR LAYOUT NAMES!!
You need to set The Adapter in this way
setListAdapter(new ListRow(this, your_theme_names_array, your_theme_icon_array));
You dont need to use ArrayAdapter for this, that is just for Creating a Adapter for an array of String
EDITED
The Layout XML does not have the problem i think.
Check the List given below one by one
Check List
Check Whether R.layout.list_view point to the layout you given in the Question.
Try this for setting adapter setListAdapter(new ListRow(this, String[] { }, int[] { })); it will show you blank screen (If you get the Blank Screen that means either THEME_NAMES or THEME_ICONS is null or their values is null)
Remove the Line imageView.setImageResource(mThemeIcons[position]); and
textView.setText(mThemeNames[position]); this will also give u blank screen (If you get blank screen then R.layout.list_view does not contain R.id.image or R.id.text.
You have to add your mListView in your ArrayAdapter in setListAdapter.Only then the contents of your listview will be display in the pattern you have mentioned in customadapter. I cannot see where you have added elements in listview.

Cannot display image correctly using custom item layout in ListView

I am using a ListView to display my custom item layout, which may contain some TextViews and an ImageView.
This is the item layout I made (post_item.xml):
<?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="60dip"
android:padding="5dip"
>
<TextView android:id="#+id/listItem_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_weight="1"
/>
<FrameLayout android:id="#+id/listItem_frameContent"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#id/userStream_listItem_title"
android:layout_weight="1"
>
</FrameLayout>
</RelativeLayout>
I don't put the ImageView initially in the xml layout, but I will insert it when I need to the FrameLayout programmatically (I also put another views in it when needed). So, there will be some items which has ImageView in it and which don't.
I get the image to fill the ImageView from the Internet (through URL), decode it as Bitmap, and keep it as a Bitmap variable in a class represents the custom item layout (class PostItem).
When the activity shows for the first time it looks fine, but as I scrolled through the items then a problem showed up, the items which shouldn't show any image show the image from the other item which should, although they don't have any ImageView (because I didn't insert it).
I am using SDK 1.6 and the emulator. Haven't tried it in real device because I don't have it.
Here is my code for the Adapter:
private class PostItemAdapter extends ArrayAdapter<PostItem> {
private List<PostItem> mPostItems;
public PostItemAdapter(Context context, int textViewResourceId, List<PostItem> postItems) {
super(context, textViewResourceId, postItems);
mPostItems = postItems;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
LayoutInflater layoutInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
view = layoutInflater.inflate(R.layout.post_item, null);
}
PostItem postItem = mPostItems.get(position);
if (postItem != null) {
final FrameLayout contentFrame = (FrameLayout) view.findViewById(R.id.listItem_frameContent);
final TextView titleTextView = (TextView) view.findViewById(R.id.listItem_title);
if (titleTextView != null) {
titleTextView.setText(postItem.getTitle());
}
if (contentFrame != null) {
if (postItem.hasImagePreview()) {
final ImageView previewImageView = new ImageView(getApplicationContext());
previewImageView.setId(LIST_ITEM_IMAGEVIEW_ID);
previewImageView.setAdjustViewBounds(true);
previewImageView.setMaxHeight(75);
previewImageView.setMaxWidth(75);
previewImageView.setImageBitmap(postItem.getImagePreview());
final RelativeLayout.LayoutParams layoutParams =
new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
contentFrame.addView(previewImageView, layoutParams);
}
if (postItem.hasContent()) {
final TextView contentTextView = new TextView(getApplicationContext());
contentTextView.setText(postItem.getContent());
final RelativeLayout.LayoutParams layoutParams =
new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParams.addRule(RelativeLayout.BELOW, LIST_ITEM_IMAGEVIEW_ID);
layoutParams.addRule(RelativeLayout.ALIGN_LEFT, LIST_ITEM_IMAGEVIEW_ID);
layoutParams.alignWithParent = true;
contentFrame.addView(contentTextView, layoutParams);
}
}
}
return view;
}
}
And this is the code to prepare the items:
/* inside a method to prepare the items */
mPostItems = new ArrayList<PostItem>();
for (int i=0; i<total); i++) {
/* operation to generate titleToDisplay and contentToDisplay */
/* contentToDisplay might be null */
mPostItems.add(new PostItem(
titleToDisplay,
contentToDisplay,
generateImagePreview()));
}
/* another method */
private Bitmap generateImagePreview(ActivityObject object) {
Bitmap imagePreview = null;
if (/*some condition*/) {
try {
InputStream inStream = (InputStream) (new URL("http://a1.typepad.com/6a010535617444970b0133ecc20b29970b-120si")).getContent();
imagePreview = Drawable.createFromStream(inStream, "linkHref");
}
catch (MalformedURLException ex) {
Log.e("INSIDE generateImagePreview()", ex.getMessage());
}
catch (IOException ex) {
Log.e("INSIDE generateImagePreview()", ex.getMessage());
}
catch (Exception ex) {
Log.e("INSIDE generateImagePreview()", ex.getMessage());
}
}
return imagePreview;
}
Is this the bug in the emulator or there is some mistake in my code (probably memory problem for the Bitmap)? Please help me, I'm really stuck in this. Any help or advice will be very appreciated. Thanks in advance :)
Cells get reused by lists and it looks like you are only altering your contentframe image if there is an image associated with the item. This means when there is no image and you are reusing a cell, it will just show whatever was passed in in the convert view. If there is no image then you should remove all children views of contentframe.
That said, you will likely get better responses in the future by being more concise. Putting up a bunch of code and taking a while to get to the issue makes it more of a chore to read and so fewer people will.

Categories

Resources