GridView isn't being displayed correctly - android

I took a screenshot of it. Its displaying some weird way:
This is the code.
The GridAdapter:
public class GridViewAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<Uri> mUrls;
// references to our images
public GridViewAdapter(Context c, ArrayList<Uri> images) {
mContext = c;
this.mUrls = images;
}
public int getCount() {
return mUrls.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater mInflater = (LayoutInflater) mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
ImageView inflatedImageView = (ImageView) mInflater.inflate(R.layout.imageview_amb_background, null);
//ImageView imageView = new ImageView(mContext);
inflatedImageView.setImageURI(mUrls.get(position));
inflatedImageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
return inflatedImageView;
}
And the inflatedImageView is a layout inflate, like this:
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="120dp"
android:layout_height="120dp"
android:background="#drawable/bgimages"
android:maxWidth="120dp"
android:padding="5dp">
</ImageView>
On the other hand, I've a gridView in a xml file:
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnWidth="250dp"
android:horizontalSpacing="5dp"
android:numColumns="3"
android:verticalSpacing="5dp" >
</GridView>
So, I inflate this gridView, I add several URI's (3 exactly) in a loop. Once added, I set the adapter to the gridview:
ArrayList<Uri> uriFotos = new ArrayList<Uri>();
HashMap<Integer, ListItem> items = xmlList.getItems();
for (int i = 0; i<items.size();i++){
ListItem itemActual = items.get(i);
itemActual.getLogoSrc();
uriFotos.add(Uri.parse(Environment.getExternalStorageDirectory().toString()+rutaFinsCarpetaClient+itemActual.getLogoSrc()));
}
gridViewInflated.setAdapter(new GridViewAdapter(this,uriFotos));
variableContent.addView(gridViewInflated);
The images are "linked" correctly.
variableContent is a LinearLayout inside a ScrollView, so the grid should be scrollable.
But as you can see few things are happening:
Height is soo big. Shouldn't it be like the inflatedImageView says?
Scroll isnt working. Well, its working but i've to move the finger around and tap several times until it works. If i stop scrolling I've to repeat the same proces until it reacts again. (SOLVED)
Hope you guys can help me. I've changed lots of layouts, changed widths, heights, and the same thing is happening.
Note that the image you see that is in the gridView, is something like 1200x800px.
Edit
The same code with smaller images:

I would try to set the Image view size to wrap_content :
android:layout_height="wrap_content"
and if you really need the 120dp height, try to reset this size after having set the image src:
inflatedImageView.setImageURI(mUrls.get(position));
inflatedImageView.setLayoutParams(new GridView.LayoutParams(120, 120));
also set the scaleType before adding the picture (preferably in the xml) :
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="120dp"
android:layout_height="120dp"
android:scaleType="centerInside"
android:background="#drawable/bgimages"
android:maxWidth="120dp"
android:padding="5dp">
</ImageView>

Related

getView in ArrayAdapter for ListFragment is called always with position=0

I have used a ListFragment with an ArrayAdapter to show a list of items. You can find the code below.
public class SelectRepiceFragment extends ListFragment {
private BuyRecipeActivity mActivity;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Resources res = mActivity.getResources();
int recipeNum = res.getInteger(R.integer.recipe_number);
String[] titles = res.getStringArray(R.array.titles);
ArrayList<RecipeItem> recipeItems = new ArrayList<RecipeItem>(recipeNum);
for (int i = 0; i < recipeNum; i++) {
RecipeItem item = new RecipeItem();
item.title = titles[i];
recipeItems.add(item);
}
RecipeItemAdapter recipeItemAdapter = new RecipeItemAdapter(mActivity, recipeItems);
setListAdapter(recipeItemAdapter);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
this.mActivity = (BuyRecipeActivity) activity;
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
mActivity.onRecipeSelected(position);
}
}
The size of recipeItems is 3 (I check it with debugger). So the getView function in ArrayAdapter should be called 3 times to generate the ListFragment. Here I have copied the ArrayAdapter.
public class RecipeItemAdapter extends ArrayAdapter<RecipeItem> {
private final Activity mActivity;
static class ViewHolder {
public MyTextView title;
public ImageView image;
}
public RecipeItemAdapter(Activity context, ArrayList<RecipeItem> recipeItems) {
super(context, R.layout.recipe_list, recipeItems);
this.mActivity = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
// reuse views
if (rowView == null) {
LayoutInflater inflater = mActivity.getLayoutInflater();
rowView = inflater.inflate(R.layout.recipe_item, null);
// configure view holder
ViewHolder viewHolder = new ViewHolder();
viewHolder.title = (MyTextView) rowView.findViewById(R.id.recipeItemTitle);
viewHolder.image = (ImageView) rowView.findViewById(R.id.recipeItemImage);
rowView.setTag(viewHolder);
}
// fill data
ViewHolder holder = (ViewHolder) rowView.getTag();
RecipeItem recipeItem = getItem(position);
holder.title.setText(recipeItem.title);
holder.image.setImageResource(R.drawable.ic_launcher);
return rowView;
}
}
The problem is that getView is actually called three times, while every time the position parameter is equal to 0. So After running the app, I just see a single row in my list instead of 3 rows.
UPDATE: I found out that I just see the first item, but if I scroll it up, then it shows the rest of items in that single row! Consequently I guessed there should be a mistake in the xml file. So I add xml files bellow.
This is my main activity xml.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- The main content view -->
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="#+id/fragmentView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|top" />
</ScrollView>
<!-- The navigation drawer -->
<ListView
android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#dcdcdc"
android:choiceMode="singleChoice"
android:divider="#dcdcdc"
android:dividerHeight="0.5dp" />
</android.support.v4.widget.DrawerLayout>
And this is my recipe_item xml file.
<?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="100dp"
android:gravity="center"
android:orientation="horizontal" >
<TextView
android:id="#+id/recipeItemTitle"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_marginLeft="10dp"
android:background="#drawable/design_price_view"
android:gravity="center" />
<ImageView
android:id="#+id/recipeItemImage"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="#drawable/app_icon" />
</LinearLayout>
UPDATE 2: I removed the DrawerLayout from my main activity xml and now I see the list. Just confusing.
You may try removing the ScrollView, take the FrameLayout out, put
layout_height="0dp"
layout_weight="1"
to the FrameLayout. You will need to manually fix the height of your navigation drawer to predefined pixel.
The above setup will make your FrameLayout & your ListView inside it take all the available space left from the navigational drawer.
The problem is, if you place a ListView inside a ScrollView - there is a rendering problem. I have not worked with ListView inside FrameLayout so cant really comment on that.
If you absolutely need to keep the ScrollView, you would need to re-render your ListView so that it spans the height it needs. Check this thread

Listview create all elements instead of visible ones

I have an issue which I didn't found any solutions on stackoverflow (or anywhere else so far).
Summary :
I have scrollview and inside of it a ListView with visibility gone (Can switch with a TextView).
When I set the adapter content, in my activity the onScroll get call with 4 visibles Item but the getView of the adapter get call for the whole dataSet (181 items) which bring a lot of performance issues / imageref_ashmem create failed ... (Of course remove image loading remove fail of creation but well :D)
=== Activity ===
Result of Activity in onScroll
firstVisibleItem 0
visibleItemCount 4
totalItemCount 181
=== Layout extract ===
<ScrollView
android:id="#+id/UserProfileView_ScrollView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:background="#00FFFFFF" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#00FFFFFF" >
<RelativeLayout
android:id="#+moreDetails/UserProfileView_BottomLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_below="#+profile/UserProfileView_MoreDetails"
android:background="#FFFFFFFF" >
<TextView
android:id="#+id/UserProfileView_About"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="center"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#ff111111"
android:visibility="gone" />
<ListView
android:id="#+id/UserProfileView_MoreDetails_ListView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:footerDividersEnabled="false"
android:divider="#color/unactivatedLightGray"
android:dividerHeight="1dp"
android:listSelector="#android:color/transparent"
android:visibility="gone" />
</RelativeLayout>
</RelativeLayout>
</ScrollView>
The height of the BottomLayout is set to 3/4 of the width of the screen programmatically.
=== Adapter ===
public class CommonAdapter extends BaseAdapter {
public List<Common> list;
private LayoutInflater inflater;
private AQuery aq;
public CommonAdapter(Context context, List<Common> list) {
this.inflater = LayoutInflater.from(context);
this.list = list;
this.aq = new AQuery(context);
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int position) {
return list.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
private class ViewHolder {
ImageView thumbImg;
TextView name;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.list_view_item, null);
holder.thumbImg = (ImageView) convertView.findViewById(R.id.CommonCell_Thumb);
holder.name = (TextView) convertView.findViewById(R.id.CommonCell_Name);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Common obj = list.get(position);
if (list.get(position).getPicture() != null)
aq.id(holder.thumbImg).image(obj.getPicture());
else
aq.id(holder.thumbImg).image(Util.Thumb(list.get(position).getId()), options);
holder.name.setText(obj.getName());
return convertView;
}
}
EDIT : Every time I scroll, the whole dataset it parse again, so 181 call to getView.
I assume your aq.id(stuff) loads an image asyncronous.
If so, check your layout/list_view_item.xml it's height is probably set to wrap_content and the ImageView also has no fixed height. Meaning while loading the image this row has a zero or very small height. Therefore all 182 rows fit into the ListView at once and getView() gets called for every single one.
Set a fixed height or minHeight for every row or the ImageView the ListView will only call getView() for as many rows fit into the ListView.
Hope this helps
I fixed the issue by set the ListView to an arbitrary Height.
<ListView
android:id="#+id/UserProfileView_MoreDetails_ListView"
android:layout_width="match_parent"
android:layout_height="1080dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:footerDividersEnabled="false"
android:divider="#color/unactivatedLightGray"
android:dividerHeight="1dp"
android:listSelector="#android:color/transparent"
android:visibility="gone" />
If ListView or RecyclerView used in ScrollView, All items will initiate at the same time.

setOnItemClickListener for GridView in PopupWindow doesn't work

If i have a GridView in a normal Activity it works fine. But here I have it in a PopupWindow, and I tried everything to get it to work, but onItemClick won't get called! I tried with the following, which were solutions for most people, but they didn't work for me (perhaps i've misused them?):
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:descendantFocusability="blocksDescendants"
Part of the activity:
bgGrid.setAdapter(new ImageAdapter(context));
bgGrid.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View v, int position, long id) {
Log.v("CLICK", "ITEM SELECTED " + position);
}
});
pw = new PopupWindow(layout, posx, posy);
pw.setOutsideTouchable(false);
pw.showAtLocation(layout, Gravity.CENTER, 0, 0); //bgGrid is part of layout
And 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:background="#444444"
android:orientation="vertical"
android:padding="5dip" >
<GridView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gridview"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:columnWidth="160dp"
android:gravity="center"
android:horizontalSpacing="10dp"
android:numColumns="auto_fit"
android:stretchMode="columnWidth"
android:verticalSpacing="10dp" >
</GridView>
<Button
android:id="#+id/popup_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:onClick="closePopup"
android:text="Close" />
</LinearLayout>
ImageAdapter
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;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) { mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(160, 120));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageResource(mThumbIds[position]);
return imageView;
}
The whole popup part is in a PereferenceActivity, where I have a listener which detects a click on Preference and opens Popup. Apparently there can be only one listener, and I can't set onClick to Preference so I don't know how to solve this (onPreferenceClick never detects any clicks). The first listener which calls the popup (the only way I could get that click):
images = (Preference) findPreference("prefs_bg");
images.setOnPreferenceClickListener(new BackgroundColorSelector());
Click is shown on the screen (I even tried drawSelectorOnTop), but no matter what, click won't get through.
recently face this problem and found solution here
popupWindow.setFocusable(true);
duplicate problem with solution:
Cannot execute OnItemClick for GridView in PopupWindow
I've found a perfect solution for me:
popUpWindow.setOutsideTouchable(true);
popUpWindow.setBackgroundDrawable(getResources().getDrawable(android.R.color.white));
popUpWindow.setFocusable(true);
The first line enables touch event outside popupwindow.
Without the second line touch event will be prevented by the popupwindow.
And the third line solves your problem.
Without the first and the two, the user interface will not response to any touch/click event when happens outside the popupwindow.
Make sure that the layouts that your ImageAdapter is inflating do not have any OnItemClickListeners registered and/or have android:focussable=false set on the Adapter layouts.
Such as:
<ImageView
android:id="#+id/imageViewIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focussable=false
/>

How to get larger icons in gridview for tablet

I made a layout with a gridview for small screens (2.7 inch). My icons are 48 x 48 px. Now i want the gridview on a tablet so i created a new layout and changed the settings to large and landscape. I want to use larger icons for the tablet: 72 x 72 px. The problem is that the larger icons not showing up but the small icons does. My small icons are in the folder drawable-mdpi and the large icons are in the folder drawable-hdpi. I tried allready to move the large icons to the drawable-xhdpi folder but without success. I also tried to change the scaletype and the layoutparams of the imageadapter but also without any success Can someone help me to get the larger icons on the tablet?
Here is my code of the large layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/back" >
<GridView
android:id="#+id/Menu"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="#+id/imageView1"
android:columnWidth="80dp"
android:gravity="center_horizontal|top"
android:horizontalSpacing="130dp"
android:numColumns="auto_fit"
android:paddingTop="10dp"
android:scrollbars="none"
android:stretchMode="columnWidth"
android:verticalSpacing="50dp" android:layout_marginTop="50dip">
</GridView>
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:src="#drawable/title" />
</RelativeLayout>
The java code of my imageadapter for the gridview is:
public class ImageAdapter extends BaseAdapter
{
private Context context;
public ImageAdapter(Context c)
{
context = c;
}
//---returns the number of images---
public int getCount() {
return menu_icon.length;
}
//---returns the ID of an item---
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
//---returns an ImageView view---
public View getView(int position, View convertView, ViewGroup parent)
{
ImageView imageView;
if (convertView == null) {
imageView = new ImageView(context);
imageView.setLayoutParams(new GridView.LayoutParams(150, 150)); imageView.setScaleType(ImageView.ScaleType.CENTER);
imageView.setPadding(5, 5, 5, 5);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageResource(menu_icon[position]);
return imageView;
}
}
Try this,
imageView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT);
This may work.
This might solve your problem:
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
http://developer.android.com/reference/android/widget/ImageView.html#setScaleType(android.widget.ImageView.ScaleType)
http://developer.android.com/reference/android/widget/ImageView.ScaleType.html

ListView very slow when scrolling (using ViewHolder/recycling)

I'm back at trying out some Android dev again. I have an "old" HTC Hero phone lying around, so I booted that one up, did some updates and are now up n running again with Eclipse and the rest.
I have Android 2.1 running on the device.
I have made a very simple test app that doesn't do anything at all except for showing some Activities and such. Even though there is no database connection, no data fetched from any network the app is very slow.
For example, I have a ListView with some custom layout items. When adding only 6-7 items (so that I get the scrolling) it is very slow when scrolling. Also, I have some buttons that changes the Activity and also that is very very slow:
mButtonListenerUPP = new OnClickListener() {
#Override
public void onClick(View v)
{
Intent myIntent = new Intent(BaseActivity.this, ActivityMain.class);
BaseActivity.this.startActivity(myIntent);
}
};
I cannot figure out why.
The Adapter, NodeRowAdapter
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.view.*;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class NodeRowAdapter extends ArrayAdapter
{
private Activity context;
private ArrayList<Node> mList;
private LayoutInflater inflater;
NodeRowAdapter(Activity context, ArrayList<Node> objects)
{
super(context, R.layout.nodepickup, objects);
this.context=context;
mList = objects;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
class ViewHolder
{
TextView name;
TextView time;
TextView road;
Node node;
}
public Node getNode(int position)
{
if (mList != null && mList.size() > position)
return mList.get(position);
else
return null;
}
public View getView(int position, View convertView, ViewGroup parent)
{
View view = convertView;
ViewHolder holder;
if (view == null)
{
view = inflater.inflate(R.layout.nodepickup, parent, false);
holder = new ViewHolder();
holder.name =(TextView)view.findViewById(R.id.name);
holder.time =(TextView)view.findViewById(R.id.time);
holder.road =(TextView)view.findViewById(R.id.road);
view.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
Node node = mList.get(position);
holder.name.setText(node.name);
holder.time.setText(node.time);
holder.road.setText(node.road);
return(view);
}
}
The main activity, ActivityMain
public class ActivityMain extends BaseActivity
{
private NodeRowAdapter _nodeRowAdapter;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SICApplication._myContext = this;
SICApplication._myContext = this;
_nodeRowAdapter = new NodeRowAdapter(this, SICApplication.dataHolder_activityMain._nodes);
ListView listView1 = (ListView) findViewById(R.id.ListViewNodes);
listView1.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
Node node = _nodeRowAdapter.getNode(position);
Log.v("MyApp", "Node=" + node.name);
}
});
listView1.setAdapter(_nodeRowAdapter);
}
/* Handles item selections */
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.add_item:
addNodeItem();
return true;
}
return false;
}
private void addNodeItem()
{
_nodeRowAdapter.add(new Node("Test", "asd asd ", "14:00", 1));
}
}
The custom list item, NodePickup
public class NodePickup extends LinearLayout
{
public NodePickup(Context context, AttributeSet attributeSet)
{
super(context, attributeSet);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.nodepickup, this);
this.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setMessage("Ajabaja!")
.setCancelable(true)
.setPositiveButton("JA!", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
dialog.cancel();
}
});
builder.show();
}
});
}
}
And lastly, the NodePickup XML layout
<LinearLayout
android:id="#+id/LinearLayout01"
android:layout_width="fill_parent"
android:layout_height="64dip"
android:orientation="horizontal"
android:background="#drawable/stateful_background"
xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:id="#+id/ImageView01"
android:layout_width="40dip"
android:layout_height="40dip"
android:src="#drawable/arrow_up_green"
android:background="#android:color/transparent">
</ImageView>
<LinearLayout
android:id="#+id/LinearLayout02"
android:background="#android:color/transparent"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:text="14:46 (15 min)"
android:id="#+id/time"
android:textSize="12dip"
android:textColor = "#000000"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent">
</TextView>
<TextView
android:text="test"
android:id="#+id/road"
android:textSize="12dip"
android:textColor = "#000000"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent">
</TextView>
<TextView
android:text="test test"
android:id="#+id/name"
android:textSize="12dip"
android:textColor = "#000000"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent">
</TextView>
</LinearLayout>
</LinearLayout>
Update
If I remove the image in the NodePickup, the lagginess is gone. The question is - why?
UPDATE 2011-08-29 If I remove the image in the NodePickup, the lagginess is gone.
The view has a hard time figuring how the layout should be rendered. The xml you posted don't help much. If you remove the ImageView then the LinearLayout02 will take all the width of the parent. But having the imageView with standar dimentions and the layout to the right will fill_parent confuses the view a lot. Requests the size of the imageView again to "push the margins to the right" (kind of). Take a look at my suggestions below
Tip1
use the LinearLayout property weight. Make the imageView fill_parent and the LinearLayout too (for the width) and play with the weight properties.
Do that also for the vertical layout with the TextViews. The best Solution whould be to put a fixed size to the height of the TextViews thought.
Also consider to change the top view to RelativeLayout. Make the image with standar dimentions , AlignParentLeft and put the LinearLayout02 toRightOf imageView. You will relief the onMeasure of the ViewGroup a lot.
Tip2
It seems like when the text changes height the whole view need to be reinflated.A common technic to avoid that it to make list Item fixed in height. So the listview can reuse the recycled views without reinflating.
Tip3
Give your LinearLayout02 a fixed height of 64dp or Fill_Parent since you don't have any left space, but the Layout don't know that and try to rearrange it self every time since the text is also Wrap_content.
Also you said that if you remove the ImageView everything is fast again.If the above don't have any effect can you please try this? Since you know that imageView size is fixed.
Extend your imageView and override requestLayout() method.
public class MyImageView extends ImageView {
public PImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public PImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PImageView(Context context) {
super(context);
}
#Override
public void requestLayout() {
/*
* Do nothing here
*/
}
}
Now include the MyImageView widget to your XML like that.
<com.package_name.MyImageView
android:id="#+id/ImageView01"
android:layout_width="40dip"
android:layout_height="40dip"
android:src="#drawable/arrow_up_green"
android:background="#android:color/transparent">
</com.package_name.MyImageView >
After optimizing my getView() method to use a holder and to reuse convertView if it's not null, my listview was still pretty laggy.
Then, I've tried
listView.setScrollingCacheEnabled(false);
and it solved it at once.
Hope this helps someone.
I just discovered this and I wanna share it with you guys.
I tried ALL the solutions provided but nothing worked. What was causing the problem is the length of the text I am feeding one of my TextView views because i'm using
mTextView.SetText(theLongString)
in my adapter in my getView method. Now that I shrinked my String, the listview is VERY smooth :)
It took a while! I tried everything. Disabling the scroll cache, viewHolder, cacheColorHint ... but nothing worked!
After searching many hours I found the root of all evil!
In my themes.xml I had a scaling background image:
<item name="android:windowBackground">#drawable/window_bg</item>
After removing the beackground everything was butter smooth.
I hope this helps someone!
To improve performance of listview use both or any one of the two - (Simple implementation)
ViewHolder
AsyncTask (a separate thread)
If you have moderately long lists I recommend ViewHolder otherwise for large lists (like in the case of a music player) I recommend using ViewHolder along with AsyncTask. The key to smooth ListView scrolling is to reduce memory consumption as much as possible.
To implement ViewHolder, is simple. Just create a static class in your custom Adapter that holds all the views that you find via findViewById. So this is how it should look -
static class ViewHolder
{
TextView text;
TextView timestamp;
ImageView icon;
ProgressBar progress;
int position;
}
Then, the next time you need to findViewById any of these views, just reference the ViewHolder like this-
ViewHolder holder = new ViewHolder();
holder.icon = (ImageView) yourView.findViewById(R.id.listitem_image);
holder.text = (TextView) yourView.findViewById(R.id.listitem_text);
holder.timestamp = (TextView) yourView.findViewById(R.id.listitem_timestamp);
holder.progress = (ProgressBar) yourView.findViewById(R.id.progress_spinner);
This is tested code and taken from one of my projects. However, the original source is here - http://developer.android.com/training/improving-layouts/smooth-scrolling.html
The lists become smoother using ViewHolder. Using AsyncTask is a little more complex, but do check out the link if you wish to implement the AsyncTask along with ViewHolder for a much smoother scrolling experience. Good Luck!
Load the image once as Bitmap and apply it to the ImageView programmatically after inflating it. If you need different images per item you should create the Bitmaps asynchronously like described in Android: How to optimize ListView with ImageView + 3 TextViews?
Try using android:cacheColorHint="#00000000" for your listview. To improve drawing performance during scrolling operations, the Android framework reuses the cache color hint.
Reference: developer.android.com article.
This Might help some one
If you have an image in your list Item, you have to remember to reduce the quality of that Image. It's allot faster to load in a few Kb's than a few megabytes.
This helped me
public Bitmap MakeFileSmaller_ToBitmap(File f) {
try {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
// The new size we want to scale to
final int REQUIRED_SIZE=200;
// Find the correct scale value. It should be the power of 2.
int scale = 1;
while(o.outWidth / scale / 2 >= REQUIRED_SIZE &&
o.outHeight / scale / 2 >= REQUIRED_SIZE) {
scale *= 2;
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {
Log.d(TAG, "FILE NOT FOUND " );
}
Log.d(TAG, "OTHER EXCEPTION");
return null;
}
I had the same issue before while i was using different layout like LinearLayout, RelativeLayout, CardView as parent of different child in same list view item. I solved that issue by changing all view inside RelativeLayout.
Using RelativeLayout as main and it's child layout may increase the speed of loading each item. So scrolling will be smooth.
<RelativeLayout
android:id="#+id/LinearLayout01"
android:layout_width="fill_parent"
android:layout_height="64dip"
android:orientation="horizontal"
android:background="#drawable/stateful_background"
xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
android:layout_width="40dip"
android:layout_height="40dip"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:id="#+id/relativeLayout">
<ImageView
android:id="#+id/ImageView01"
android:layout_width="40dip"
android:layout_height="40dip"
android:src="#drawable/arrow_up_green"
android:background="#android:color/transparent">
</ImageView>
</RelativeLayout>
<TextView
android:text="14:46 (15 min)"
android:id="#+id/time"
android:textSize="12dip"
android:textColor = "#000000"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/relativeLayout"
android:layout_toEndOf="#+id/relativeLayout" />
<TextView
android:text="test"
android:id="#+id/road"
android:textSize="12dip"
android:textColor = "#000000"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:layout_below="#+id/time"
android:layout_toRightOf="#+id/relativeLayout"
android:layout_toEndOf="#+id/relativeLayout" />
<TextView
android:text="test test"
android:id="#+id/name"
android:textSize="12dip"
android:textColor = "#000000"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:layout_below="#+id/road"
android:layout_toRightOf="#+id/relativeLayout"
android:layout_toEndOf="#+id/relativeLayout"/></RelativeLayout>
You can use
listview.setScrollingCacheEnabled(false).When scrolling listview application hold area then throwing Out Of Memory(OOM) exception.My solution is worked for me.

Categories

Resources