android listView row height - android

I implemented a listview with 2 kinds of rows from here listViews with multiple rows tutorial
all is working properly,
the problem that I have now is setting the height for the rows,
if I leave the background as a color, all is good,
but if I use an image for background, I only get a tall row [on other simple list views the height respect the programatically set height], but in this case, the row changes
so
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/category_item_row"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:background="#ff00ff"
android:layout_height="70dp"
android:padding="3dp"
>
<ImageView
android:id="#+id/image"
android:layout_width="40dp"
android:layout_height="70dp"
android:gravity="center_vertical"/>
<TextView
android:id="#+id/title"
android:textSize="20sp"
android:layout_width="90dp"
android:layout_height="70dp"
android:gravity="center_vertical"/>
</LinearLayout>
works fine,
but
android:background="#drawable/phone_cat_cell">
is not respecting the assigned height,
how to fix this height using my image background?
thanks!
edit 1, adapter
listViewItem.setAdapter(new PhoneItemAdapter(new ItemPhoneDataSource().getItems()));
private class PhoneItemAdapter extends BaseAdapter {
final List<RowPhone> rows;//row
//data source, style
PhoneItemAdapter(List<ItemPhone> animals) {
rows = new ArrayList<RowPhone>();//member variable
//choose cell! iterator
for (ItemPhone item : animals) {
//if it has an image, use an ImageRow
if (item.getImageId() != null) {
rows.add(new RowFolderPhone(LayoutInflater.from(getActivity()), item)); //imageRow!
} else {//otherwise use a DescriptionRow
rows.add(new RowItemPhone(LayoutInflater.from(getActivity()), item));
}
}
}
//delegate
#Override
public int getViewTypeCount() {
return RowTypePhone.values().length;
}
#Override
public int getItemViewType(int position) {
//con cast
return ((RowPhone) rows.get(position)).getViewType();
}
public int getCount() {
return rows.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
//cambiado con cast!
return ((RowPhone) rows.get(position)).getView(convertView);
}
}

Check your adapter code, if you are passing null while inflating the view then please replace that code with this.
view = inflater.inflate(R.layout.listview_row, parent, false);

you just need to make not static images, but "9patch" images.
All android versions are supporting that.
Have a look here http://developer.android.com/tools/help/draw9patch.html

Try this:
<ImageView
android:id="#+id/image"
android:layout_width="40dp"
android:layout_height="70dp"
android:scaleType="fitXY"
android:adjustViewBounds="true"
android:gravity="center_vertical"/>

Related

RecyclerView - Layout_weight is ignored when it loads first time

I have an Activity that contains a Fragment. Fragment contains a RecyclerView, displaying CardViews.
CardView is very simple, just a TextView and a CustomView. This is the layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="100dp">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="100dp"
android:id="#+id/card_current_heat_cardview"
android:layout_gravity="center_vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:weightSum="4">
<TextView
android:id="#+id/card_current_heat_textview"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textStyle="bold"
android:textColor="#000000"
android:background="#android:color/holo_red_dark"
android:gravity="center_vertical"/>
<com.amige.vm2.CurrentHeatChartView
android:id="#+id/card_current_heat_chart_view"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"/>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
TextView should use 1/4 of the width, and the CustomView 3/4.
Im having trouble understanding why weights are ignored the first time the RecyclerView loads
Image of RecyclerView loaded for the first time
But if I scroll up and down, the layout works as expected for some Cards
Image of RecyclerView scrolled up and down
I also have another Activity (no fragment involved here) that has a RecyclerView and IS using this same CardView Layout and it works perfectly!!
I dont know if it has to do with the Fragment...
What am I missing?
Thanks!
EDIT
This the Adapter code
public class MainAdapter extends RecyclerView.Adapter<MyFragment.MainAdapter.ViewHolder>
{
public MainAdapter()
{
}
#Override
public MyFragment.MainAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_current_heat, parent, false);
return new MyFragment.MainAdapter.ViewHolder(v);
}
#Override
public void onBindViewHolder(MyFragment.MainAdapter.ViewHolder holder, int position)
{
if (arrayList.size() == 2)
{
if (position == 0)
{
holder.variableNameTextView.setText(“Var Name”);
holder.currentHeatChartView.reloadChartWithSamples(arrayList.get(0));
}
else
{
if ((position - 1) < arrayList.get(1).size())
{
HashMap variableHashMap = (HashMap) arrayList.get(1).get(position - 1);
holder.variableNameTextView.setText(variableHashMap.get("VarName") != null ? (String)variableHashMap.get("VarName") : "");
holder.currentHeatChartView.reloadChartWithVariableValuesAndColors(variableHashMap, colorGradientsArrayList.get((position - 1) % colorGradientsArrayList.size()));
}
}
}
}
#Override
public int getItemCount()
{
if (arrayList.size() == 2)
{
if (arrayList.get(1).size() > 0)
{
return 1 + arrayList.get(1).size();
}
else
{
return 1;
}
}
return 0;
}
public class ViewHolder extends RecyclerView.ViewHolder
{
TextView variableNameTextView;
CurrentHeatChartView currentHeatChartView;
public ViewHolder(View v)
{
super(v);
this.variableNameTextView = (TextView) v.findViewById(R.id.card_current_heat_textview);
this.currentHeatChartView = (CurrentHeatChartView) v.findViewById(R.id.card_current_heat_chart_view);
}
}
}
I found the culprit.
There was a ConstraintLayout on top of the hierarchy of the Activity containing the Fragment. Since I was working with nested layouts, ConstraintLayout was not the right way to go.
I changed it to RelativeLayout and the cards are now rendered properly.
I think your layout inflation is wrong.
View view = View.inflate(mContext, R.layout.your_layout, null);
If you do like that change your code like this.
View view = LayoutInflater.from(mContext).(R.layout.your_layout, parent, false);
Hope it helps:)

How to make a galleryview item fill parent width

I am trying to use a Gallery View (knowing its deprecated) as an horizontal GridView. It's OK, but now i want to make it display only one item at the time, meaning each item fills the width of the parent.
Here is my XML (minimalistic at this time, just a LinearLayout) :
<LinearLayout
android:id="#+id/profile"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/galleryLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/gallerylabeltext"
android:layout_marginBottom="10dp"
android:textSize="#dimen/small_text_size" />
<Gallery
android:id="#+id/mygallery"
android:layout_width="fill_parent"
android:layout_height="80dp"
android:gravity="center" />
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#android:color/darker_gray" />
</LinearLayout>
How can i achieve that ? Extending the Gallery Class ? In the XML ?
Thanks in advance for your help.
try this adapter for gallary,
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
aQuery = new AQuery(c);
}
public int getCount() {
return myImageList.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
#SuppressWarnings("deprecation")
public View getView(final int pos, View arg1, ViewGroup arg2) {
ImageView i = new ImageView(mContext);
i.setLayoutParams(new Gallery.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
i.setScaleType(ScaleType.FIT_XY);
i.setImageResource(myImageList[pos]);
return i;
}
}
you can try to use "RelativeLayout" replace the "LinearLayout" in XML ,i have once to use Gallery display only one item at the time

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.

Horizontal ScrollView in List View Item Android

I have a list view with 20 rows and I want to setup a horizontal scrollview for every row item in list view, as each row contains more than one item.
Here is my code :
<?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:orientation="horizontal" >
<HorizontalScrollView
android:id="#+id/hor_scroll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none" >
<LinearLayout
android:id="#+id/mainLinear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
</LinearLayout>
</HorizontalScrollView>
</RelativeLayout>
Inner Row Layout which is to be replicated in a row any number of times
<ImageView
android:id="#+id/icon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginRight="6.0dip"
android:src="#drawable/ic_launcher" />
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:text="Example Value"
android:textAppearance="?android:textAppearanceMedium" />
BaseAdapter
public class HorizontalListViewAdapter extends BaseAdapter {
private Context context;
private ArrayList<ArrayList<DwivediJi>> dataSet;
public HorizontalListViewAdapter(Context context) {
this.context = context;
}
#Override
public int getCount() {
return 20;
}
#Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return arg0;
}
#Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return arg0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.horizontal_list_item, null,false);
LinearLayout mainLinnerLayout=(LinearLayout)convertView.findViewById(R.id.mainLinear);
for (int i = 0; i <5; i++) {
View additionView = inflater.inflate(R.layout.inner_layout_file, null,false);
LinearLayout innerLinnerLayout=(LinearLayout)additionView.findViewById(R.id.inner_layout);
mainLinnerLayout.addView(innerLinnerLayout);
}
return convertView;
}
class ViewHolder {
TextView tv_titleExample;
HorizontalScrollView hzView;
LinearLayout linear_layout,main_linear_layout;
}
}
My Problem
Look at the screenshot attached. My problem is that more than one view is showing at one time in each row.
I want that only one view should show to the user at one time and for the rest all the user has to do is swipe left to right or right to left.
Note: Not an ideal solution, but should provide what you want..
Another Note: This may make your listview slightly janky, depending on the layout-complexity
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.horizontal_list_item, null,false);
LinearLayout mainLinnerLayout=(LinearLayout)convertView.findViewById(R.id.mainLinear);
for (int i = 0; i <5; i++) {
View additionView = inflater.inflate(R.layout.inner_layout_file, null,false);
LinearLayout innerLinnerLayout=(LinearLayout)additionView.findViewById(R.id.inner_layout);
// If the width varies for each innerLinnerLayout, then remove the if block & always calculate padding value
// padding is an integer initialized to -1 in the constructor
if (padding == -1) {
int width = context.getResources().getDisplayMetrics().widthPixels;
innerLinnerLayout.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
padding = width - additionView.getMeasuredWidth();
}
// I've set padding to right only, but you could center it by giving left and right padding of value=(padding/2)
innerLinnerLayout.setPadding(0, 0, padding, 0);
mainLinnerLayout.addView(innerLinnerLayout);
}
return convertView;
}
The problem is with your adapter as:
getCount() from your adapter must return the total number from list. Returning 20 is not valid in your context - and you seem to have 20 items in your list. You should return dataSet.size();
getItem() should return the item from the model data structure, in this case:
Below
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return dataSet.get(position);
}
Also, your getView method must return the view that displays the model data at given at position parameter. Returning a ViewGroup with non-meaningfull dummy data is what you currently have. You should get the ArrayList<DwivediJi> from parameter position (through dataSet.get(position)) and construct/inflate a View that displays properly this data structure item.
Change inner layout width to match_parent. This should help you
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="#+id/icon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginRight="6.0dip"
android:src="#drawable/ic_launcher" />
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:text="Example Value"
android:textAppearance="?android:textAppearanceMedium" />
</LinearLayout>
Seems you are adding your inner layout in this LinearLayout
<LinearLayout
android:id="#+id/mainLinear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
</LinearLayout>
Did you try changing its width to match_parent too??
Use scrollview in xml layout and then dynamically create HorizontalScrollView inside for loop:
example :
for(int i.......) //number of HorizontalScrollView needed
{
HorizontalScrollView mainlinear = new HorizontalScrollView(
getApplicationContext());
for(int i.......) //number of items wants to add in HorizontalScrollView
{
// adding any widgets as per your requirements
}
mainlinear.addView(Widgetname);
scroll.addView(mainlinear);
}

Trying to make listview items non-clickable

I have listview that I have populated into a alertDialog When the alertDialog displays the user are able to click on these items in the listview and that is when the problem comes in. I do not want the user to be able to click on the items in the listview and I have already tried adding this to my xml layout android:clickable="false" and android:focusable="false" but I am still getting the same results. Can somebody assist me with this issue that having.
Here is my base adapter class:
public class MyAdapter extends BaseAdapter {
final String[] listItemsFirstRow = {"Item1","Item2"};
final String[] listItemSecondRow = {"Item1", "Item2"};
#Override
public int getCount() {
return listItemsFirstRow.length;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null)
{
LayoutInflater layoutInflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.twolinelistview, null);
}
((TextView)convertView.findViewById(R.id.text1)).setText( listItemsFirstRow[position]);
((TextView)convertView.findViewById(R.id.text2)).setText( listItemSecondRow[position]);
return convertView;
}
}
And here is my xml layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:gravity="center_vertical"
android:paddingLeft="15dip"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:textAppearance="?android:attr/textAppearanceMedium"
android:id="#+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false" />
<TextView
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
android:id="#+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false" />
</LinearLayout>
Modify your BaseAdapter to override isEnabled to tell the ListView that the items aren't clickable.
Example:
#Override
public boolean isEnabled(int position) {
return false;
}
Note that the documentation says this will do exactly what you want:
Returns true if the item at the specified position is not a separator. (A separator is a non-selectable, non-clickable item)
Try setting android:clickable="false" and android:longClickable="false" for your ListView in XML, or you can set it before you set the adapter as well. That should be enough to disable it, but if not android:focusable="false" and android:enabled="false" should definitely do it.
If you are just trying to prevent items from being highlighted another option is to change how it displays selected items and ignoring the events. One way that was suggested in an older question is:
android:listSelector="#android:color/transparent"
android:cacheColorHint="#android:color/transparent"

Categories

Resources