I created a custom adapter with an xml with root layout as linear Layout. When i tried to change the root to RelativeLayout to add a button at the right end, each time i inflate the adapter by pressing the button the app stops working
This is my xml with the relative layout that isn't working when run
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/laybackground"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="#dimen/list_item_height"
android:background="#color/tan_background"
android:orientation="horizontal">
<ImageView
android:id="#+id/theImage"
android:layout_width="#dimen/list_item_height"
android:layout_height="#dimen/list_item_height"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_toRightOf="#id/theImage">
<TextView
android:id="#+id/mokWord"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
tools:text="mok"
android:textColor="#android:color/white"/>
<TextView
android:id="#+id/engWord"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
tools:text="eng"
android:textColor="#android:color/white"/>
</LinearLayout>
</RelativeLayout>
And this is my Adapter
public class WordAdapterClass extends ArrayAdapter<MokAndEngClass> {
public int col=0;
public WordAdapterClass(Activity context, #NonNull List<MokAndEngClass> objects,int backroundColor) {
super(context, 0, objects);
col=backroundColor;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View v = convertView;
if(v==null)
{
LayoutInflater lv = LayoutInflater.from(getContext());
v=lv.inflate(R.layout.englishandmoaki,parent,false);
}
MokAndEngClass listItem = getItem(position);
if(listItem!=null){
TextView writtenInMok = (TextView)v.findViewById(R.id.mokWord);
TextView writtenInEng =v.findViewById(R.id.engWord);
ImageView realtedImage =v.findViewById(R.id.theImage);
LinearLayout theTextLayout =(LinearLayout) v.findViewById(R.id.laybackground);
writtenInEng.setText(listItem.getEngWord());
writtenInMok.setText(listItem.getMokWord());
if(listItem.putAnImage()==0)
realtedImage.setVisibility(View.GONE);
else
realtedImage.setBackgroundResource(listItem.putAnImage());
theTextLayout.setBackgroundColor(theTextLayout.getResources().getColor(col));
}
return v;
}
}
The problem is you have changed the layout type from LinearLayout to RelativeLayout without changing the code in the getView() method to reflect that change--you are still trying to cast the root view to an LinearLayout!
Change this line of code:
LinearLayout theTextLayout =(LinearLayout) v.findViewById(R.id.laybackground);
to
RelativLayout theTextLayout =(RelativeLayout) v.findViewById(R.id.laybackground);
and everything should work as before.
Please Note:
When you post a question in the future on SO and you are reporting an issue, please make it clear that "isn't working" actually means "getting an error" and you should post the stack trace from the logcat. This issue would have been clear-up in 10 seconds by the SO community.
Related
I have problem that my list view is not showing and the getView method never invoked
here is my list view inside the onCreate in the MainActivity
l = (ListView) findViewById(R.id.listvv);
CustomAdapter adapter = new CustomAdapter(MainActivity.this, maainimg);
l.setAdapter(adapter);
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#color/white"
tools:context=".MainActivity">
<ListView
android:id="#+id/listvv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:divider="#b4be"
android:dividerHeight="2dp"></ListView>
<LinearLayout
android:id="#+id/ad_holder"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|bottom"
android:layout_alignParentBottom="true">
<com.google.android.gms.ads.AdView
android:id="#+id/adView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
ads:adSize="BANNER"
ads:adUnitId="#string/BottomBanner">
</com.google.android.gms.ads.AdView>
</LinearLayout>
</LinearLayout>
and here is my CustomAdapter Class it is inside the MainActivity
public class CustomAdapter extends ArrayAdapter<String> {
int[] img;
Activity activity;
ImageButton imageButton;
public CustomAdapter(Activity act, int [] images) {
super(act, R.layout.custom_row);
this.activity=act;
this.img=images;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.d("getView","Called!");
View row = convertView;
if(row==null){
LayoutInflater inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.custom_row, parent, false);
imageButton = (ImageButton) row.findViewById(R.id.preview);}
imageButton.setImageResource(img[position]);
Log.d("added",position+"");
if (getSelectedcolor() == 0) {
imageButton.setColorFilter(Color.RED);
setSelectedcolor(Color.RED);
} else {
imageButton.setColorFilter(Color.parseColor(colorToHexString(getSelectedcolor())));
}
return row;
}
}
and the custom_row.xml
<?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="match_parent"
android:background="#color/background">
<ImageButton
android:id="#+id/preview"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="10dp"
android:src="#drawable/ic_1_red"
android:scaleType="fitXY"
android:background="#drawable/roundedbutton"
/>
</LinearLayout>
Update
here is my array maainimg its not empty
maainimg = new int[]{R.drawable.ic_1_red,R.drawable.ic_2_red,R.drawable.ic_3_red,R.drawable.ic_4_red,R.drawable.ic_5_red,R.drawable.ic_6_red,
R.drawable.ic_7,R.drawable.ic_8,R.drawable.ic_8,R.drawable.ic_9,R.drawable.ic_10,R.drawable.ic_11,R.drawable.ic_12
,R.drawable.ic_13,R.drawable.ic_14,R.drawable.ic_15,R.drawable.ic_16,R.drawable.ic_17,R.drawable.ic_18,R.drawable.ic_19,R.drawable.ic_20,
R.drawable.ic_21,R.drawable.ic_22,R.drawable.ic_23,R.drawable.ic_24,R.drawable.ic_25};
While you call super(act, R.layout.custom_row); (without passing the objects), you need to override getCount() method, otherwise your adapter can't figure out how many items you have, and this is why there is no call of getView() method.
#Override
public int getCount(){
return img.length;
}
The first problem I see is your Layout.
<ListView
android:id="#+id/listvv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:divider="#b4be"
android:dividerHeight="2dp"></ListView>
<LinearLayout
android:id="#+id/ad_holder"
android:layout_width="fill_parent"
Your ListView has no room left because the bottom linear layout is using FILL_PARENT (which is deprecated btw, use MATCH_PARENT instead).
Try making your ListView height (and width) to be both MATCH_PARENT. And then deal with the "Ad".
You could have the LinearLayout replaced by a RelativeLayout and have the Ad pin at the bottom of its parent and below the listview.
Second: Why are you using an ArrayAdapter<String> if you're internally using an array of int.
Third: since you're using the wrong type of adapter, you're not correctly implementing it, you need to override more methods (getCount() for example), to tell the underlying adapter: hey, this is the number of items we have.
Since you're not using the provided array of strings, but your custom array of ints that you pass during construction, try overriding getCount() and return the size of your int array instead.
I this there is a issue in your Adapter class, Try this, But keep in mind that there are cleaner ways of writing this same code,
public class CustomAdapter extends ArrayAdapter<Integer> {
int[] img;
Context context;
ImageButton imageButton;
public CustomAdapter(Context context, Integer [] images) {
super(context, R.layout.custom_row, images);
this.context=context;
this.img=images;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.d("getView","Called!");
View row = convertView;
if(row==null){
LayoutInflater inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.custom_row, parent, false);
}
imageButton = (ImageButton) row.findViewById(R.id.preview);
imageButton.setImageResource(img[position]);
Log.d("added",position+"");
if (getSelectedcolor() == 0) {
imageButton.setColorFilter(Color.RED);
setSelectedcolor(Color.RED);
} else {
imageButton.setColorFilter(Color.parseColor(colorToHexString(getSelectedcolor())));
}
return row;
}
}
I am developing an android application which contains a ListAtivity class and get it is data as follow :
ArrayAdapter<Item> ara=new MyArrayAdapter(this,_items);
setListAdapter(ara);
And I defined MyArrayAdapter :
....
public MyArrayAdapter(Activity context, List<BirthdayContact> list) {
super(context,R.layout.list_row,0,list);
//super(context, R.layout.birthday_list, list);
this.context = context;
this.list = list;
}
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
LayoutInflater inflator = context.getLayoutInflater();
view = inflator.inflate(R.layout.birthday_list_row, null);
final ViewHolder viewHolder = new ViewHolder();
viewHolder._cName= (TextView) view.findViewById(R.id.contact_name);
viewHolder._cImage = (ImageView) view.findViewById(R.id.contact_image);
viewHolder._cbirthDay=(TextView)view.findViewById(R.id.contact_birthday_remained);
view.setTag(viewHolder);
}
......
But the problem with this way is that you cant only assign each row`s template and you cant have other widget on list view which are not part of list of data. I mean I want to have a say a TextView which shows messages to user, and below that I show the list of rows.
Can you help me please?
If you want a different layout than a simple ListView you have the option of setting the content view to a layout file like this:
setContentView(R.layout.layout_with_diferrent_views); // call this on the onCreate() method
where R.layout.layout_with_different_views could be a xml layout like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
Because you extends ListActivity you must have in the layout a ListView element with the id #android:id/list. Of course you can have a more complex layout than the one above as long as you have a ListView element with the id #android:id/list
You should consider using a listHeader : lv.addHeaderView(findViewById(R.id.header));
This has to be done in your onCreate method in your activity, and you must provide a widget with the id header.
If you want other components in activity.Then better consider Normal Activity instead ListActivity.
I'm having a weird problem, in my rather complex view layout. (I will try to simplify it a bit in my explanation)
Basically I have a ListView, where each item consists of a TextView and an ImageButton. I am able to either click the list item (on the textview), or the button (I set the ImageButton to non-focusable, otherwise it wouldn't work)
Now it seems to work fine, until I open another window and return to the listview.
From that point on, I can click the ImageButton without anything happening (not even the background changes during the click). But when I click on the TextView again, all the click events from the ImageButton are dispatched at once.
Why is that?
EDIT:
The List Item:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="0px"
android:minHeight="40dp"
android:orientation="horizontal"
android:paddingLeft="2px"
android:paddingRight="2px"
>
<TextView
android:id="#+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Text"
android:textSize="19dp"
android:paddingTop="4px"
android:paddingBottom="4px"
android:layout_gravity="center_vertical"/>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/open_subtree_layout"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="0px"
android:orientation="horizontal"
android:padding="0px">
<View
android:layout_width="1px"
android:layout_height="match_parent"
android:background="#drawable/separator_line" />
<com.treeviewer.leveldisplay.DontPressWithParentImageButton
android:id="#+id/btn_right"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:background="#drawable/list_selector_background"
android:focusable="false"
android:focusableInTouchMode="false"
android:padding="10dp"
android:src="#drawable/arrow_right" />
</LinearLayout>
</LinearLayout>
That's how it is inflated:
[...]
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mView = inflater.inflate(R.layout.tree_row, null, false);
TextView textView = (TextView)mView.findViewById(R.id.text1);
LinearLayout nextNodeButtonContainer = (LinearLayout)mView.findViewById(R.id.open_subtree_layout);
if(childCount >= 0) {
titleBuilder.append(" (" + childCount + ")");
nextNodeButtonContainer.setVisibility(View.VISIBLE);
View button = nextNodeButtonContainer.findViewById(R.id.btn_right);
button.setFocusable(false);
button.setFocusableInTouchMode(false);
//button.setClickable(true);
button.setOnClickListener(clickListener);
button.setTag(tagValue);
} else {
nextNodeButtonContainer.setVisibility(View.GONE);
}
textView.setText(titleBuilder);
Let me know, if you need more code.
Ok, I finally solved this problem.
Unfortunately, in my question I didn't provide the necessary information to solve it, as the problem was somewhere I didn't expect it:
I have a ListAdapter where the getView method looks like this:
public View getView(int position, View convertView, ViewGroup parent) {
return mNodes.get(position).getView(mNodeArrowClickListener, position);
}
And the getView method of the nodes (TreeLevelElements) looked like:
public class TreeLevelElement {
private final Context mContext;
private View mView = null;
//[...] other methods
View getView(OnClickListener clickListener, final int tagValue) {
if(mView == null) {
//[...] produce a new View from XML
}
return mView;
}
}
The problem was, that I stored the Views in my elements, so I guess that conflicted somehow with android strategy to reuse old views for new items.
I don't know what exactly happened, but now that I removed mView and create a new one every time, it works.
I will also change it to reuse the convertView instead.
In my listadapter code, I would like to indent my view. To do that i add some left padding but that doesnt seem to work.
EDIT: main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<LinearLayout
android:layout_width="80dip" android:layout_height="fill_parent"
android:gravity="right|center_vertical">
<ImageView android:id="#+id/item_image" android:layout_width="wrap_content"
android:src="#drawable/icon" android:layout_height="wrap_content"></ImageView>
</LinearLayout>
<FrameLayout android:id="#+id/frame"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_weight="1" >
</FrameLayout>
</LinearLayout>
any suggestions why padding would not work ?? I want to move the image x dp to the right.
#Override
public final View getView(final int position, final View convertView, final ViewGroup parent) {
if (convertView == null) {
final LinearLayout layout = (LinearLayout) layoutInflater.inflate( R.layout.main, null);
layout.setPadding(100, 8,8,8);
return layout;
} else {
//do stuff
}
}
thanks
try this code
#Override
public final View getView(final int position, final View convertView, final ViewGroup parent) {
final View layout = View.inflate(context, R.layout.main, null);
layout.setPadding(100, 8,8,8);
return layout;
}
You are taking the reference of a xml file ..... you should get reference to the layout defined in xml file or any other view of xml file to set params ......
You can set param on the view not on xml file....
If setting padding does not work, you could always try:
layout.offsetLeftAndRight(100);
I guess .. you can give padding in your xml layout using android:padding...... (left or right or top or bottom) . Specifying them in xml layout file will indent the ImageView as per requirements.
Is there a site where I can find the inner workings of the BaseExpandableListAdapter? I read the API and I still don't understand how it loops through the whole array that is supplied to provide the view. I'm having problems with my own implementation. I can't create a whole list of expandable lists without using ExpandableListActivity, even though both are the same. It's supposed to retrieve strings from the database and create an expandablelistview out of each one, and add all the created expandablelists to a linearlayout inside main.xml. What happens is that only the expandablelistview for the first string is shown. Here's the snippet
Main Class:
public class MainActivity extends Activity implements OnClickListener {
DBAdapter groupTable = new DBAdapter(this);
ExpandableListView groupLabel;
GroupAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
groupTable.open();
adapter = new GroupAdapter(groupTable.getAllGroups());
retrieveExpandables(adapter);
groupTable.close();
Button addGroupButton = (Button)findViewById(R.id.addGroup);
addGroupButton.setOnClickListener(this);
}
public void retrieveExpandables(GroupAdapter adapter) {
LinearLayout layout = (LinearLayout)findViewById(R.id.grouplist);
LinearLayout groupLayout =
(LinearLayout)getLayoutInflater().inflate(R.layout.grouplistview, null);
ExpandableListView groupExpandableList =
(ExpandableListView)groupLayout.findViewById(R.id.groupLabel);
groupExpandableList.setAdapter(adapter);
layout.addView(groupLayout);
}
BaseExpandableListAdapter class:
#Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
if (convertView instanceof ViewGroup)
return (ViewGroup) convertView;
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
ViewGroup item = (ViewGroup)inflater.inflate(R.layout.grouplisttext, null);
TextView groupLabel = (TextView)item.findViewById(R.id.groupLabel);
groupLabel.setText(groups[groupPosition].name);
groupLabel.setVisibility(View.VISIBLE);
Log.d("A1", "This part repeating");
return item;
}
XML file for the TextView that will be the expandable list title
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:id="#+id/groups"
android:layout_height="wrap_content">
<TextView android:id="#+id/groupLabel"
android:textSize="24sp"
android:text="asdf"
android:textStyle="bold"
android:layout_width="fill_parent"
android:layout_weight="1"
android:layout_height="40dip"
android:layout_marginLeft="45dip"
android:gravity="center_vertical" />
</LinearLayout>
XML file for the ExpandableListView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:id="#+id/groups"
android:layout_height="wrap_content">
<ExpandableListView android:id="#+id/groupLabel"
android:textSize="24sp"
android:textStyle="bold"
android:layout_width="fill_parent"
android:layout_weight="1"
android:layout_height="40dip" />
</LinearLayout>
Sorry if I posted too much code, I tried removing as much unnecessary information as possible.
I found out where the problem went wrong. Apparently I got the LinearLayout and the ScrollView inside the main.xml interchanged, and the method for getViewGroup class was wrong. It's all good now