the problems is, that I wan't to make ListView with elements which are containing image, description and two buttons. I'm making them in my own BaseAdapter extension, but fragment which is containing ListView is closing (wihtout errors in logcat..). I've found, that ListView is working well, when I'm not returning layout-type elements. So there is my sample with 'sample linear layout', which is not working.. Is there any possibility, to show layouts in ListView?
Here is my code:
Creating part:
lv = (ListView) getView().findViewById(R.id.main_wall_ambajes_lv);
AmbajAdapter aa = new AmbajAdapter(getActivity().getApplicationContext(), StaticData.ambajes);
lv.setAdapter(aa);
My getView method from adapter:
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout ll = new LinearLayout(getActivity());
ll.setOrientation(LinearLayout.VERTICAL);
ImageView iv = new ImageView(getActivity());
iv.setImageBitmap(placeholderBitmap);
ll.addView(iv);
ll.addView(iv);
ll.addView(iv);
ll.addView(iv);
return ll;
}
I don't know why you don't have any error however I don't think you proceed the correct way.
Usually you create the layout in the xml file of the layout folder and only inflate it in the getView(), for example as follow :
private LayoutInflater mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
#Override
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
view = mInflater.inflate(R.layout.your_custom_layout, parent, false);
}
//your code for setting the image or other things goes here
//for example if you have a textView
TextView textView = (TextView) view.findViewById(R.id.my_textview_id);
textView.setText("my custom text for this cell");
return (view);
}
and your_custom_layout is simply the xml file of your layout.
Note that for performance reason due to cell recycling I only inflate the view when it is null and I only read once the LayoutInflater context and put it in mInflater. However for the best performance you should use a ViewHolder, but it is out of the scope of your question.
Related
I'm using a LinearLayout which contains an ImageView and a HorizontalScrollView as ListView items.
The problem is OnItemClickListener of the ListView doesn't work. After adding android:descendantFocusability="blocksDescendants" on LinearLayout it works when ImageView is clicked but it doesn't work when HorizontalScrollView is clicked.
android:focusable="false" and android:focusableInTouchMode="false" doesn't work too.
I want regular clicks on HorizontalScrollView also fires OnItemClickListener of ListView.
I'm testing on android 4.2.2
I had the same problem and did not find any better solution than just to assign View.onClickListener to descendant of HorizontalScrollView. In my case I needed to know the position value from ArrayAdapter belonging to the clicked listview item, which I passed to the view during the getView execution as a view tag.
RelativeLayout -> HorizontalScrollView -> Relative Layout #+id/clickit ...
public View getView(int position, View convertView, ViewGroup parent)
{
layoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(resourceID, parent, false);
MyType mt = getItem(position);
RelativeLayout rl = (RelativeLayout) rowView.findViewById(R.id.clickit);
rl.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
m_menuEventsListener.onActionsMenuClick(getItem((Integer) view.getTag()));
}
});
rl.setTag(position);
}
Note that the same m_menuEventsListener.onActionsMenuClick is called from the onItemClickListener attached to the listview. m_menuEventsListener is my own listener implemented in the Activity.
Each item in my gallery is a custom view. One of the child's view is a gridView. When I'm scrolling the gallery everything works fine, but it wont scroll by touching the gridView. Its difficult to explain, I hope someone will understand me!
Touching and scrolling any part of the custom view suppose to trigger the scrolling? Or maybe only the imageView will trigger the scrolling?
public View getView(int position, View convertView, ViewGroup parent) {
final SubProduct subProduct=subProducts.get(position);
int quantity=subProduct.getQuantity();
int size=subProduct.getSizes().get(0).getWidth();
String productName=subProduct.getProductName();
int productPrice=subProduct.getSizes().get(0).getPrice();
int columnWidth = 0;
View view=convertView;
if (view==null){
holder=new SubProductHolder();
//The main container
holder.myLinearLayout= new LinearLayout(this.myContext);
holder.myLinearLayout.setOrientation(1);//vertical
//The custome button
LayoutInflater inflater = (LayoutInflater)
myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v=(View)inflater.inflate(R.layout.custom_sub_product_layout, null);
LinearLayout btnLayout = (LinearLayout)v.findViewById(R.id.customSunProductButtonLayout);
LinearLayout.LayoutParams llp = new LinearLayout.LayoutParams(PRODUCT_BOTTUN_WIDTH,PRODUCT_BOTTUN_HEIGHT);
btnLayout.setLayoutParams(llp);
tvSubProductDescription=(TextView)v.findViewById(R.id.tvSubProductDescription);
tvSubProductPrice=(TextView) v.findViewById(R.id.tvSubProductPrice);
holder.btnProduct=btnLayout;
holder.btnProduct.setGravity(Gravity.CENTER);
holder.TvLinearLayout= new LinearLayout(this.myContext);
holder.TvLinearLayout.addView(holder.btnProduct);
//frame
holder.image = new ImageView(this.myContext);
holder.image.setBackgroundColor(Color.WHITE);
LinearLayout.LayoutParams llp2 = new LinearLayout.LayoutParams(FRAME_WIDTH,FRAME_WIDTH);
holder.image.setLayoutParams(llp2);
//grid
holder.grid=new GridView(myContext);
//the number of rows is the round number of quantity sqaure
int numberOfColomns=(int) Math.floor((int) Math.sqrt(quantity));
holder.grid.setNumColumns(numberOfColomns);
holder.grid.setLayoutParams(new RelativeLayout.LayoutParams(PRODUCT_PICTURE_WIDTH,PRODUCT_PICTURE_WIDTH));
}else{
holder=(SubProductHolder)view.getTag();
}
//set text in description tv
tvSubProductDescription.setText(quantity+" "+productName+" "+size+"X"+size);
tvSubProductPrice.setText("$"+productPrice);
//set the grid
holder.grid.setAdapter(new emptySquaresAdapter(quantity,myContext,columnWidth,columnHeight));
holder.relativeGridLayout=new RelativeLayout(myContext);
holder.relativeGridLayout.addView(holder.image);
holder.relativeGridLayout.addView(holder.grid);
//set button and picture to layout
holder.myLinearLayout.addView(holder.relativeGridLayout);
holder.myLinearLayout.addView(holder.TvLinearLayout);
return holder.myLinearLayout;
}
static class SubProductHolder
{
ImageView image;
GridView grid;
RelativeLayout relativeGridLayout;
LinearLayout btnProduct;
LinearLayout TvLinearLayout;
LinearLayout myLinearLayout;
}
You have to use TouchListeners for galleryView since on clicking on its child view will not trigger scroll for galleryView
You have to use TouchListeners. Also, you're better off going with a ViewPager and using fragments. To my knowledge, Gallery is deprecated.
I am making bar charts in custom list view. when I scroll list, components get shuffle. How can it be stopped.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.stats_row_layout, null);
}
Stat stat = objects.get(position);
if (stat.isFlag()) {
LinearLayout linearLayout = (LinearLayout) convertView.findViewById(R.id.parentLayout);
linearLayout.setVisibility(LinearLayout.VISIBLE);
} else {
LinearLayout linearLayout = (LinearLayout) convertView.findViewById(R.id.parentLayout);
linearLayout.setVisibility(LinearLayout.GONE);
}
if (!stat.isExist()) {
stat.setExist(true);
LinearLayout linearLayout = (LinearLayout) convertView.findViewById(R.id.statGraphLayout);
linearLayout.removeAllViews();
if (stat.getmView() == null) {
ImageView mView = new StatBarChartVie(context, stat.getStatValues());
stat.setmView(mView);
}
LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, 50);
stat.getmView().setLayoutParams(params);
linearLayout.addView(stat.getmView());
}
}
return convertView;
}
Using the visible / gone flags doesn't seem right in a list view.
Because of how a list view recycles views, that is probably the problem.
You may need to be a bit smarter about how you access the array. And not include invisible items in the count.
Whenever you change the data ( possibly overriding notifyDataSetChanged() calling its super), you could create a new Index ArrayList with only the values which are visible. So you no longer need to use the invisible settings. This way you only loop through the array on data changes.
I created the Layout design using java code only not from the XML Layout Designs. The code I used is following
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv = new TextView(mContext);
tv.setText(hotelList.get(position).name);
return tv;
}
How to use layoutInflator for creating layout fro this. I need 2 more textviews in a single list item. the whole list contains 10 different list items
Please provide some codes for this. Help appreciated
I have gone through this before by having my static class too. Check this out, it will help:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
if ( rowView == null) {
LayoutInflater inflator = this._activity.getLayoutInflater();
rowView = inflator.inflate(R.layout.todolistlisting, null);
TodoListViewHolder viewHolder = new TodoListViewHolder();
viewHolder._name = (TextView) rowView.findViewById(R.id.tVTLName);
viewHolder._completed = (TextView) rowView.findViewById(R.id.tVTLCCount);
viewHolder._remaining = (TextView) rowView.findViewById(R.id.tVTLRCount);
rowView.setTag(viewHolder);
}
TodoListViewHolder holder = (TodoListViewHolder) rowView.getTag();
VO_TodoList votodolist = this._items.get(position);
holder._name.setText(votodolist._title);
holder._completed.setText(votodolist._completed);
holder._remaining.setText(votodolist._remaining);
return rowView;
}
TodoListViewHolder is my view component holder here. like your TextView.
I guess you know how to make XML layout for this layout. So just make the XML layout and get the object of the main layout using the following code:
LinearLayout mainLayout=(LinearLayout) View.inflate(R.layout.yourlayout); //if yourlayout.xml is the name of the xml file you made and put in the layout folder.
To get the child of the layout, let's say if it's a TextView with the id text, then the code would be:
TextView textView=(TextView)mainLayout.findViewById(R.id.text);
You can add view at runtime by using inflater like this
LinerLayout linearLayout = (LinearLayout)inflater.inflate(R.layout.news_categories_item, null);
TextView categoryValueTextView = (TextView)linearLayout.findViewById(R.id.news_category_item_value);
mMainLinearLayout.addView(categoryValueTextView);
Here i am inflating one text view which is there in another linear layout(this is simple linear layout which holds only textview) at runtime and adding it to my main linear layout.
you can get the inflater object in your acitivity by using getLayoutInflater(). And if you want to get inflater in adapter you have to pass inflater object to constructor of adapter from your activity.
I have made a ListView with an ArrayAdapter. It works. But I had to put the resource id for the item layout twice: in the adapter definition and in the getView, in the case when the View parameter is null.
// --------------------------------------------here is the FIRST use
lvShows.setAdapter(new ArrayAdapter<TvShow>(this, R.layout.show_row, allKnownShows) {
#Override
public View getView(int position, final View rowView, ViewGroup parent) {
LinearLayout showView;
if (rowView == null) {
// --------------------------------- here is the SECOND use
showView = (LinearLayout) inflater.inflate(R.layout.show_row, parent, false);
}
else {
showView = (LinearLayout) rowView;
}
((TextView) showView.getChildAt(0)).setText(time));
((TextView) showView.getChildAt(1)).setText(name);
return showView;
}
});
Such style is disgustful, of course. Could you kindly advise, what am I understanding wrong and how can I use the resource only once?
If creating a new ArrayAdapter I am setting the layout id, it should know it and use somehow. How could I reach it? Or better I would expect the Adapter to create item views automatically. Again - how can I use it?
What ArrayAdapter does with that resource we feed to it when creating a new one? All its constructors take the item resource and we manage this resource and inflate it "by hand". It is not the effective way.
You can override ArrayAdapter constructor and call super :
public ArrayAdapter<T>(Context context, TheDataType data) {
super(context, R.layout.show_row, data);
}
And store the id in a ArrayAdapter member variable. It avoid the adapter "user" to know what is the view needed for the adapter.
Or you can use a BaseAdapter.
I had looked into the source code of the ArrayAdapter, and it already does all this stuff about view creation:
// citation from public class ArrayAdapter<T>
private View createViewFromResource(int position, View convertView, ViewGroup parent,
int resource) {
View view;
TextView text;
if (convertView == null) {
view = mInflater.inflate(resource, parent, false);
} else {
view = convertView;
}
So, we should simply use it:
lvShows.setAdapter(new ArrayAdapter<TvShow>(this,
R.layout.show_row,
R.id.nameField,
allKnownShows){
public View getView(int position, final View convertView, ViewGroup parent) {
LinearLayout showView = (LinearLayout) super.getView(position, convertView, parent);
setAnythingForItem(showView);
return showView;
}
Attention: we have changed the constructor!
ArrayAdapter allows to use no-TextView item layout. But if it is not TextView itself, it should have one and the id of this very inner TextView field should be given to the constructor as the third parameter. ArrayAdapter needs it to be set, to write there Strings if the array connected to it has String elements.
It wants a TextView always, even if it doesn't need it really, if the array consists of Objects, not Strings. Otherway it checks the item layout for being a TextView and if it is not, throws an error.