I have a Listview inside a Scrollview and manually binding its data on the code behind. My main problem is, when I bind my data, my listview isn't expanding its height. I've tried setting it to wrap_content, fill_parent but nothing works. Here is my XML
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/parentScrollview"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<RelativeLayout
>
<LinearLayout >
<ImageView
/>
<LinearLayout
>
<TextView />
<TextView />
<LinearLayout >
<TextView/>
<TextView/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView/>
<TextView />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<View />
<TextView/>
<ScrollView
android:id="#+id/childScrollView"
android:layout_width="match_parent"
android:layout_height="375dp"
android:layout_below="#+id/view1"
android:layout_centerHorizontal="true"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:layout_marginTop="18dp"
android:background="#drawable/scrollviewborder"
android:scrollbarStyle="insideInset" >
<ListView
android:id="#+id/listFriends"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="2dip"
android:paddingLeft="2dip"
android:paddingRight="2dip"
android:paddingTop="2dip"
>
</ListView>
</ScrollView>
<Button />
</RelativeLayout>
</ScrollView>
Please see that it is a nested ListView and here is my code behind
ArrayList<HashMap<String, String>> friendList = new ArrayList<HashMap<String, String>>();
// adding database values to HashMap key => value
for (int i = 0; i < friendName.length; i++) {
// creating new HashMap
HashMap<String, String> friend = new HashMap<String, String>();
//merchant.put(KEY_ID, merchantIdArray[i]);
friend.put(KEY_FRIEND_NAME, friendName[i]);
friend.put(KEY_THUMB_URL,imageIDs[i]);
friendList.add(friend);
}
list=(ListView)findViewById(R.id.listFriends);
adapter =new LazyAdapter(this, friendList);
list.setAdapter(adapter);
What seems to be the problem?
EDIT
Ive added this code for validating which scroll should be used
parentScrollView= (ScrollView) findViewById(R.id.parentScrollview);
parentScrollView.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
//Log.v(TAG,"PARENT TOUCH");
findViewById(R.id.childScrollView).getParent().requestDisallowInterceptTouchEvent(false);
return false;
}
});
childScrollView= (ScrollView) findViewById(R.id.childScrollView);
childScrollView.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
//Log.v(TAG,"PARENT TOUCH");
findViewById(R.id.childScrollView).getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
The main reason about this is that I will put my Facebook friendlist inside this Listview that it should be scrollable
The problem is the following (as stated here by Romain Guy):
Using a ListView to make it not scroll is extremely expensive and goes
against the whole purpose of ListView. You should NOT do this. Just
use a LinearLayout instead.
#Androyd Friend its always better if u dont put listview inside scrollView and also not scrollview inside listview,
abd then make listview fill parent or fix some hieght in dps like 300dp or that much height u want...
Related
I have a listview which occupies all the space of the layout IN THEORY, but actually it occupies only half of the layout because it has got only 5 elements and it doesn't cover all the screen. I'd like to know when I touch OUTSIDE of the listview. I tried to create a clicklistener method for the layout of the listfragment which contains the list, but it is never used because IN THEORY the listview occupies all the layout, so the click isn't found. It is the same for the layout of the activity more or less. In that case the click is found only on the edges, so I can't find a method to solve my problem.
Here is the fragment layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#android:id/list" />
Here is the activity layout:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="com.example.utente.actionbar.MainActivity">
<Button
android:text="MULTI"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="26dp"
android:id="#+id/button" />
<Button
android:text="SINGOLO"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/button"
android:layout_alignLeft="#+id/button"
android:layout_alignStart="#+id/button"
android:layout_marginBottom="25dp"
android:id="#+id/button2" />
IN THEORY the listview occupies all the layout
Not a theory, that is exactly what happens; by using android:layout_height="match_parent" the View will always take the full screen height.
listView.setOnClickListener would work if you want to see if you clicked anywhere in the ListView, but you typically would instead want listView.setOnItemClickListener to see if you have clicked on any single item, and not the entire list.
Refer: difference between onClickListener and onItemClickListener
If you really want to shrink the ListView, then android:layout_height="wrap_content" is an option, but I'm not sure that works without content actually being loaded into that View since the content wrapping is applied at inflation-time, which since it has no adapter set, can't be done.
If you are needing to detect a listener literally "outside the ListView", then you need to set some type of click / touch listener on the rootView of that Fragment.
public View onCreateView(...) {
rootView = inflater.inflate(...);
listView = ...;
listView.setOnTouchListner(...
#Override
public boolean onTouch(View v, MotionEvent event) {
return false; // Says that click was not handled here.
}
});
rootView.setOnTouchListner(...
// TODO: Check if click landed outside the ListView
#Override
public boolean onTouch(View v, MotionEvent event) {
if (v.getId() != android.R.id.listView) { // Not the list
if (event.getAction() == MotionEvent.ACTION_UP) {
// Up action more reliable than "down"
return true;
}
}
}
);
return rootView;
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content" <!-- Or specific height -->
android:id="#android:id/list" />
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/clickView" />
</LinearLayout>
In Fragmet
public View onCreateView(...) {
rootView = inflater.inflate(...);
View clickView = rootView.findViewById(...);
clickView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Do something here
}
});
return rootView;
}
I guess this solves your problem.
I am making an android application containing a listview which updates every 30 seconds. If there is new data, I want a button to appear where I can update the feed, similar to the facebook app. How can I accomplish this? Is there a way to overlay a button on top of a listview that appears at the top of the screen when not scrolling in the listview?
Here is my listview xml:
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/list"
android:layout_width="fill_parent"
android:paddingLeft="3dp"
android:paddingRight="3dp"
android:layout_height="wrap_content"
android:layout_below="#id/header"
android:divider="#android:color/transparent"
android:dividerHeight="10dp"
/>
</LinearLayout>
<Button
android:id="#+id/update_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:text="Button" />
Try using the setOnScrollListener and implement the onScrollStateChanged.
setOnScrollListener(new OnScrollListener() {
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
//make your button invisible
button.setVisible(false);
}
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) {
//make your button visible.
button.setVisible(true);
}
}
});
Overlaying of views can be seen here.
So I have simple listview with a list item that contains a textview, and two imageviews.
I want both of the imageviews to act as buttons. Unfortunately, I can't even get one of them to work. The list view loads but then the app crashes when either image is touched. Here is the xml for the listitem:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/bg_card">
<TextView
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textColor="#color/Black"
android:id="#+id/name"
android:textSize="20sp"
android:padding="16dp">
</TextView>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_gravity="right"
android:gravity="right">
<ImageView
android:layout_width="40dp"
android:layout_height="fill_parent"
android:id="#+id/email"
android:clickable="true"
android:src="#drawable/ic_action_email"
android:layout_margin="8dp"/>
<View
android:layout_width="2dp"
android:layout_height="match_parent"
android:background="#color/LightGrey" />
<ImageView
android:layout_width="40dp"
android:layout_height="fill_parent"
android:id="#+id/internet"
android:clickable="true"
android:layout_margin="8dp"
android:src="#drawable/ic_action_web_site" />
</LinearLayout>
</LinearLayout>
Here is the layout with the listview:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/lvDepartments"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="#android:color/transparent"
android:dividerHeight="8dp"
android:padding="8dp"
android:smoothScrollbar="true"
android:scrollbarStyle="insideOverlay"
android:listSelector="#color/Navy"/>
</LinearLayout>
Here is the related java code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.staff_layout);
staffmemberlist = (ListView)findViewById(R.id.lvDepartments);
ArrayAdapter<String> arrayAdapter =new ArrayAdapter<String> (getApplicationContext(),R.layout.emailbrowsingcard,R.id.name, d);
staffmemberlist.setAdapter(arrayAdapter);
mailbutton=(ImageView)findViewById(R.id.email);
mailbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(),
"This line would appear on clicking this icon",
Toast.LENGTH_LONG).show();
}
});
}
this isnt going to work because the ImageView is in the item list so you should consider doing..
mailButton = (ImageView) row.findViewById(R.id.email);
where row is the item list. remember the ImageView isn't in staff_layout, it is in your item_layout.
to make it works you need to move this block:
mailbutton=(ImageView)findViewById(R.id.email);
mailbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(),
"This line would appear on clicking this icon",
Toast.LENGTH_LONG).show();
}
});
to the getView() in your adapter class. and let the View get findViewById or have an instance of the item_layout view in order to reach the buttons.
you should use a custom adapter for that and in custom adapter use findViewById for finding imageviews and setting listener
this is a good tutorial: http://www.vogella.com/articles/AndroidListView/article.html
I have two xml files. One of them contains the ListView and the one who populates the listView. I was
able to display the items but the thing is, it can't be scrolled. For example, I have list of items to display but it will not automatically enables scroll. Which part of the code should be enhanced so that it will allow scrolling. I know that listView enables scrolling by default. Please help me with this one. Thanks in advance.
public class ActivityViewCategory extends ListActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_products);
// Hashmap for ListView
productsList = new ArrayList<HashMap<String, String>>();
// Get listview
ListView lv = getListView();
.
.
.
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all products
pDialog.dismiss();
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
/**
* Updating parsed JSON data into ListView
ArrayList<HashMap<String, String>> com.example.restotrial.ActivityViewCategory.productsList * */
ListAdapter adapter = new SimpleAdapter(
ActivityViewCategory.this, productsList,
R.layout.list_item, new String[] { TAG_PID,
TAG_NAME},
new int[] { R.id.pid, R.id.name });
// updating listview
setListAdapter(adapter);
}
});
}
}
activity_view_products.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<!-- Main ListView
Always give id value as list(#android:id/list)
-->
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="456dp" >
</ListView>
</LinearLayout>
list_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<!-- Product id (pid) - will be HIDDEN - used to pass to other activity -->
<TextView
android:id="#+id/pid"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone" />
<!-- Name Label -->
<TextView
android:id="#+id/name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="6dip"
android:paddingLeft="6dip"
android:textSize="17dip"
android:textStyle="bold" />
</LinearLayout>
I think it would work better if you used the constraints of a RelativeLayout to contain your ListView.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<!-- Main ListView
Always give id value as list(#android:id/list)
-->
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_height="wrap_content" >
</ListView>
</RelativeLayout>
The visual top of your ListView will be at the top of the parent view, the visual bottom will be at the bottom of the parent view, and your content will be as long as your list happens to be, and scroll where it needs to.
I have read about problems that onClickListener will consume onItemClickListener Events like here or here. My Problem is exactly the other way:
I have a CustomAdapter extends ArrayAdapter where I place model Objects to generate a row. In My Activity i registered an onItemClickListener like so
//items can focus false to try to get the onItemClick-event
mListView.setItemsCanFocus(false);
mListView.setOnItemClickListener(this);
mListView.setAdapter(this.favoritePointAdapter);
then in my Adapter.getView() Method I inflate my layout get my ImageView and register an OnClickListener on it like this
#Override
public View getView(int position, View convertView, ViewGroup parent){
//....inflate other Views.....
LinearLayout clickArea = (LinearLayout)convertView.findViewById(R.id.list_row_favorite_point_click_area);
clickArea.setOnClickListener(this);
//... other logic follows ...
}
at least i Try to fetch this Events in my Adapter like this
#Override
public void onClick(View v) {
Log.d("ListAdapter", "onClick triggered");
//never triggered
switch (v.getId()) {
case R.id.list_row_favorite_point_click_area:
Log.d("ListAdapter", "onClick id->list_row_favorite_point_click_area");
//never triggered
break;
default:
break;
}
}
If you find xml of RowView interesting, here it is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/list_row_relative_parent"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:focusable="false">
<LinearLayout
android:id="#+id/list_row_icon"
android:layout_width="30dip"
android:layout_height="30dip"
android:layout_gravity="center_vertical"
android:layout_margin="3dip"
/>
<LinearLayout
android:layout_weight="50"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center_vertical">
<TextView
android:id="#+id/list_row_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#333333"
android:text="defaultText"
android:textStyle="bold" />
<TextView
android:id="#+id/list_row_region"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#999999"
android:textStyle="italic"
android:text="Region" />
</LinearLayout>
<LinearLayout
android:id="#+id/list_row_favorite_point_click_area"
android:layout_width="50dip"
android:layout_height="50dip">
<ImageView
android:id="#+id/list_row_favorite_icon"
android:layout_width="20dip"
android:layout_height="20dip"
android:layout_gravity="center_vertical"
android:layout_weight="0.1">
</ImageView>
</LinearLayout>
</LinearLayout>
As I said, The ListView's onItemClick of My Activity gets triggered while I never reach onClick inside my Adapter. I think that onItemClick 'feels' responsible for the whole row and consumes TouchEvents. What can I do to work around it?
Note: I tried setItemsCanFocus(false) and focusable in my root to false, too, as mentioned in the other questions.
Rather than using an onClickListener, I'd suggest using the onTouchListener.
Check out this tutorial, which I have used before to get the "swipe screens" in an application:
http://www.warriorpoint.com/blog/2009/05/29/android-switching-screens-by-dragging-over-the-touch-screen/
Also, see the android dev docs on the onTouchListener:
http://developer.android.com/reference/android/view/View.OnTouchListener.html