I have been trying to make a layout for my app, where I set the android:layout_height="wrap_content".
This is my code ::
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.hp.money.DashBoard">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:id="#+id/cv_amount_display"
android:layout_width="match_parent"
android:layout_height="200dp">
.....
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
card_view:cardCornerRadius="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/last_10_transaction" />
<ListView
android:id="#+id/last_transactions_lv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
</ScrollView>
I am using a ListView inside a ScrollView, which is a bad idea, I know! It leads to some scrolling issues, I believe. But I have to dynamically update data on my screen during runtime, and I think only the listview can handle it. If there's any other View to do it, please suggest.
Now, the problem is that even if the Data source of the ListView has 10 items, the height of the ListView always remains equal to the size of one listView element, but the height of the listview is set to wrap_content, so probably it is supposed to resize accordingly. But it doesn't! How to fix this?
This is how it looks, even though the Listview has 10 items!
The ListView is the one which has a heading as LAST 10 TRANSACTIONS
Why I used a ScrollView??
I put a scrollview, because, the number of enteries in the listview can be many, so I want that when the user scrolls to see the entries not currently visible int the listview, the whole page gets scrolled, and not only the listview.
What do you mean by " dynamically insert data into the Listview during runtime". If you are modifying list data dynamically then ListView can handle it internally. You no need to do anything in that case. So you can remove the ScrollView so it works fine.
You can not add a ListView inside ScrollView .
For considering your needs you can set ListView height dynamically to fulfill your needs ...
After setting up your list adapter simply call this method...
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
As others pointed, you can't put a ListView inside a ScrollView (anyways it doesn't make sense, ListView has its own scroll)
But I have to dynamically insert data into the Listview during runtime, if there's any other way to do it, please suggest.
I can't see why you think you can't, and want to know why you think a ScrollView will do it.
If you have created your own adapter to fill that ListView you should have something like this:
class listViewAdapter extends BaseAdapter
{
public View getView(int position, View convertView, ViewGroup parent)
{
}
public int getCount()
{
}
public Object getItem(int position) {
}
public long getItemId(int position){
}
}
Then you should create a data field and a setter
private Arraylist<DataType> data;
public void setData(Arraylist<DataType> data)
{
data = data;
}
Then you can use it like this:
ListView lv = findViewById...
ListViewAdapter adapter = new ListViewAdapter();
adapter.setData(data);
lv.setAdapter(new ListViewAdapter());
When you have added or deleted data you can reload it by calling
adapter.notifySetDataChanged();
Related
I am currently trying to use a preference fragment within a Navigation Drawer. There are multiple preference fragments that may populate a frame layout, all of which could be of a different size and may not be the full height of the parent.
For this reason I was wanting to use wrap_content for the frame layout height, but as preference fragment extends from ListView this causes problems (reference ListView Wrap Content). wrap_content does provide the desired result, although I can see that OnBindView is being called continuously, which highly inefficient and causes my data binding methods to be called all the time.
Has anyone got any simple out the box solutions I could try? Or would this be a case for a custom View where I would measure the children of the fragment and set the height at run time? Any help on this would be much appreciated.
The layout below shows the drawer layout which is included in the main layout.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:orientation="horizontal"
android:padding="20dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RadioGroup
android:id="#+id/drawer_radio"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RadioButton
android:id="#+id/drawer_radio_button_0"
style="#style/ButtonDrawer"
android:background="#drawable/fft_button"
android:button="#null"
android:contentDescription="#string/image_button"/>
<RadioButton
android:id="#+id/drawer_radio_button_1"
style="#style/ButtonDrawer"
android:background="#drawable/trigger_button"
android:button="#null"
android:contentDescription="#string/image_button"/>
</RadioGroup>
</LinearLayout>
<FrameLayout
android:id="#+id/drawer_preference_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
tools:layout="#android:layout/simple_list_item_1"
android:background="#drawable/floating_preference_background_shape"/>
</LinearLayout>
Ok, so I think I found a good solution so I thought I'd post it for others to use.
The way I had to do this was to extend from PreferenceFragment and do some measurements at run time, in which I can use to resize the listView.
I did this with the following.
public class PreferenceFragmentHeightWrap extends PreferenceFragment {
/**
* We can guarantee that all children will be in the adaptor list by this point
*/
#Override
public void onResume() {
super.onResume();
setListViewHeightBasedOnItems(getView());
}
/**
* Sets ListView height dynamically based on the height of the items.
*
* #return true if the listView is successfully resized, false otherwise
*/
public boolean setListViewHeightBasedOnItems(View view) {
ListView listView = (ListView) view.findViewById(android.R.id.list);
ListAdapter listAdapter = listView.getAdapter();
if(listAdapter != null) {
int numberOfItems = listAdapter.getCount();
// Get total height of all items.
int totalItemsHeight = 0;
for(int itemPos = 0; itemPos < numberOfItems; itemPos++) {
View item = listAdapter.getView(itemPos, null, listView);
item.measure(0, 0);
totalItemsHeight += item.getMeasuredHeight();
}
// Get total height of all item dividers.
int totalDividersHeight = listView.getDividerHeight() *
(numberOfItems - 1);
// Set list height.
ViewGroup.LayoutParams params = view.getLayoutParams();
params.height = totalItemsHeight + totalDividersHeight + listView.getPaddingBottom()
+ listView.getPaddingTop();
view.setLayoutParams(params);
return true;
} else {
return false;
}
}
Hopefully this will make sense and feel free to comment if you see anything untoward.
I would like to have a ScrollView that contains a ListView, which is obviously undesirable since a ListView has its own scroll bar.
Essentially I would like to have a RelativeLayout with a number of views forming the header of the page, followed by a ListView, similar to Facebook's profile page with the images followed by the feed.
If I simply put a ListView inside a RelativeLayout then only the ListView area is scrollable instead of the whole page.
Is there a way to do this without including the header (RelativeLayout) as the first element in the ListView?
It looks like there is a method on ListView called addHeaderView. I can use this to add the RelativeLayout at the top. Thanks for your input.
Actually I haven't done this myself, but I kinda know the trick to achieve your goal and give a sexy look to your layout.
First get rid of that ScrollView.
Then put a monitor(listener) on your ListView to detect how much your ListView has scrolled and consider a reasonable threshold to detect *.
Now what is * ? it is the time you should "Hide" or "slowly fade" your header items. when user scrolls down the ListView and reaches that threshold slowly fade or hide the header. Then again when user scrolls up use a threshold to decide when to make your header items visible.
As far as I know this is the idea. Also try checking github and android-arsenal I guess there should be a library for this that will ease your work.
Use this class
public class Helper {
public static void getListViewSize(ListView myListView) {
ListAdapter myListAdapter = myListView.getAdapter();
if (myListAdapter == null) {
// do nothing return null
return;
}
//set listAdapter in loop for getting final size
int totalHeight = 0;
for (int size = 0; size < myListAdapter.getCount(); size++) {
View listItem = myListAdapter.getView(size, null, myListView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
//setting listview item in adapter
ViewGroup.LayoutParams params = myListView.getLayoutParams();
params.height = totalHeight + (myListView.getDividerHeight() * (myListAdapter.getCount() - 1));
myListView.setLayoutParams(params);
// print height of adapter on log
Log.i("height of listItem:", String.valueOf(totalHeight));
}
}
and in the activity class, use,
Helper.getListViewSize(ur listview name);
Try this Code.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp" >
<LinearLayout
android:id="#+id/headerLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="TextView" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="TextView" />
</LinearLayout>
<ListView
android:id="#+id/listView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/headerLayout" >
</ListView>
</RelativeLayout>
I have a profile page contains a linearlayout with some textviews and imageviews and a listview. (See picture)
The problem is that I want to make the whole page scrollable like in the twitter app instead of only the listview. So the listview need to extend to max height.
How can i force the listview to extend to max size and not be scrollable.
I linearlayout would be a second option but then it need to be possible to add a custom arrayadapter with a custom row like in the listview.
You can make this in two ways:
#1 Adding Header to your Listview
View header = inflater.inflate(R.layout.your_header_layout, null);
yourlistview.addHeader(header);
#2 You can set the list view height based on children.Call this fxn with your listview and keep all your widgets inside scrollview.
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
return;
}
int totalHeight = 0;
for (int i = 0, len = listAdapter.getCount(); i < len; i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight
+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
Yes you can put the scroll view as parent view and make your custom class for your list view.
You can check my answer by this link
list view in scroll view
Use ScrollView to wrap your layout:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/scrollview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
......
</LinearLayout
</ScrollView>
Keep in mind that ScrollView takes in only one child. So adjust your original layout accordingly.
This a ListView screenshot of my problem:
This is the layout XML:
<LinearLayout
android:id="#+id/viewer_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/background_dark"
android:orientation="vertical" >
<EditText
android:id="#+id/viewer_filter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableRight="#android:drawable/ic_menu_search"
android:hint="#string/hint_filter"
android:background="#android:color/white"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="3dp"
android:inputType="text"
android:paddingLeft="4dp"
android:selectAllOnFocus="true" >
</EditText>
<EditText
android:id="#+id/viewer_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableRight="#android:drawable/ic_menu_search"
android:hint="#string/hint_search"
android:background="#android:color/white"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginTop="3dp"
android:layout_marginBottom="5dp"
android:inputType="text"
android:paddingLeft="4dp"
android:selectAllOnFocus="true" >
</EditText>
</LinearLayout>
<HorizontalScrollView
android:id="#+id/viewer_hscroll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/viewer_top" >
<ListView
android:id="#+id/viewer_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</ListView>
</HorizontalScrollView>
There are 3 problems in this scenario:
The Horizontal scrollview does not cover the full screen width (I drew a thick red line to mark the end)
The Horizontal scrollview does not scroll horizontally
The ListView rows are not of uniform width (this can be seen by the background color ending) (see the getView code below for details)
private static final int listRowLayout = android.R.layout.activity_list_item;
private Map<String, Integer> mColors = new HashMap<String, Integer>();
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// No logs here to keep ListView performance good
ViewHolder holder;
int color;
if( convertView == null ) {
convertView = mInflater.inflate(listRowLayout, parent, false);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(android.R.id.text1);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
String data = mData.get(position);
// A compiled regex is faster than String.Contains()
Matcher m = ViewHolder.regex.matcher(data);
if( m.find() ) {
color = mColors.get(m.group(1));
} else {
color = mColors.get("V");
}
holder.text.setText(data);
holder.text.setBackgroundColor(color);
return convertView;
}
private static class ViewHolder {
TextView text;
static Pattern regex = Pattern.compile(" ([VIDWEF])/");
}
}
I encountered the exact same issue in trying to display a log file. I have a dedicated activity to display the log file:
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_log);
// Read in lines from the log file
File clientLogFile = new File(LOG_FILE);
ArrayList<String> lines = new ArrayList<String>();
try
{
Scanner scanner = new Scanner((Readable) new BufferedReader(new FileReader(clientLogFile)));
try
{
while(scanner.hasNextLine())
{
lines.add(scanner.nextLine());
}
}
finally
{
scanner.close();
}
}
catch (FileNotFoundException e)
{
lines.add("No log file");
}
// Create a simple adaptor that wraps the lines for the ListView
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item,lines);
// Create a ListView dynamically to overide onMeasure()
final ListView listView = new ListView(this)
{
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
// Override onMeasure so we can set the width of the view to the widest line in the log file
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// Find maximum width of item in list and set scroll width equal to that
int maxWidth = 0;
for(int i=0; i<getAdapter().getCount(); i++)
{
View listItem = getAdapter().getView(i, null, this);
listItem.measure(0, 0);
int width = listItem.getMeasuredWidth();
if(width > maxWidth)
{
maxWidth = width;
}
}
// Set width of measured dimension
setMeasuredDimension(maxWidth, getMeasuredHeight());
}
};
// Add to scroll view
HorizontalScrollView horizontalScrollView = (HorizontalScrollView)findViewById(R.id.logScrollView);
horizontalScrollView.addView(listView);
// Set adaptor
listView.setAdapter(adapter);
// Enable fast scroll
listView.setFastScrollEnabled(true);
// Scroll to end
listView.post(new Runnable(){
public void run() {
listView.setSelection(listView.getCount() - 1);
}});
}
The onCreate method reads the log file and then dynamically adds a ListView to a HorizontalScrollView with onMeasure() overridden. The onMeasure() code determines the maximum width of the views in the adaptor and sets the ListView width to be that.
My activity_view_log.xml layout file is therefore very simple:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="5dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingTop="5dp"
>
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/logScrollView">
</HorizontalScrollView>
</RelativeLayout>
In order to have finer grained control of the lines in the ListView I give my adapter my own layout file in list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:inputType="text|none"
/>
At the end of by onCreate() I enable fast scroll and also scroll to the end of the lines in the log file.
I would probably reverse what you are doing. Create a ListView and make each item in the listview horizontally scrollable. This way items only scroll when they need to, and it does not scroll the entire screen. And you get complete control over the dimensions of each list item. To do this use a custom listview adapter as mentioned in the comments. There is also a possible duplicate of your question here: Android horizontal scroll list
In order to solve the 3 problems I had to make all the components (the horizontal scroll view, the list view and it's items) have a "fill_parent" width (I think it's the same as "match_parent"). In addition I had the listview's onMeasure(...) overridden to calculate the max width of it's items and set it via setMeasuredDimension(...). This will measure the view by it's widest item, not by it's first, as it is implemented now.
This is the solution I found.
The root of all evil :-) is that ListView is not designed to efficiently deal with rows of different length. To determine the ListView width, instead of looking at all the rows, only 3 rows are taken as average.
So, if the 3 rows are by chance short rows, the width will be clipped for the longer rows, it explains the problems I experienced.
To bypass this I calculated the maximum row length for all data, and I padded shorter rows with spaces, it solved all 3 problems I described in the question.
The code for padding (executed inside getView() )
holder.text.setText(String.format("%1$-" + mLen + "s", data));
I encountered a problem when embedding a ListView inside a ScrollView, or at least that's where I guess the problem comes from. The ListView element is a fairly simple one:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/item_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/general_background_list_middle"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:paddingRight="0dp"
android:paddingLeft="0dp">
<ImageView
android:id="#+id/chat_friends_avatar"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_marginLeft="7dp"
android:layout_marginRight="8dp"
android:paddingRight="0dp"
android:paddingLeft="0dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:src="#drawable/friends_icon_avatar_default"/>
<TextView
android:id="#+id/chat_message_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/chat_friends_avatar"
android:layout_alignParentTop="true"
android:layout_marginRight="35dp"
android:maxLines="10"
android:textSize="12dp"/>
<TextView
android:id="#+id/chat_friend_name"
android:layout_width="140dp"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
style="#style/SubText"
android:layout_toRightOf="#id/chat_friends_avatar"
android:layout_below="#id/chat_message_text" />
<TextView
android:id="#+id/chat_message_time"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_marginTop="3dp"
style="#style/SubText"
android:layout_alignParentRight="true"
android:layout_below="#id/chat_message_text" />
</RelativeLayout>
However, when I embed a list of such elements in a ScrollView, in between some other elements, the rows are not fully displayed, they are clipped (see image below) if the text is wrapped. The ListView is instantiated as follows in the ScrollView:
<ListView
android:id="#+id/info_chat_listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:cacheColorHint="#color/frame_background_color"
android:clickable="false"
android:divider="#null"
android:footerDividersEnabled="false"
android:focusable="false" >
</ListView>
If the height of the ListView is set to "wrap_content" only the first element is shown. That's why I'm using a method to calculate the height of the rows of the list:
private int getCommentsListHeight() {
if (mChatAdapter != null && mChatAdapter.getCount() != 0) {
if (mChatList != null) {// && mCommentsListItemHeight == 0) {
mCommentsListItemHeight = 0;
for (int i = 0; i < mChatAdapter.getCount(); i++) {
// Get view item height
View viewItem = mChatAdapter
.getView(i, new View(OnAirActivity.this), mChatList);
viewItem.measure(0, 0);
Logger.d(LOGTAG, "View " + i + " measured height = " + viewItem.getMeasuredHeight());
mCommentsListItemHeight += viewItem.getMeasuredHeight();
}
}
//return mChatAdapter.getCount() * mCommentsListItemHeight;
return mCommentsListItemHeight;
} else {
return 0;
}
}
Unfortunately, in case when the text inside the TextView is wrapped, even over several lines, the height of the row element returned by the getMeasuredHeight() method is constant. Also the getLineCount() called on the TextView inside the row element returns 1 even if the text is wrapped.
On the other hand, if this ListView is embedded in a LinearLayout, everything works fine and the full list is displayed with no clipping.
Do you have any suggestions as to what might be wrong here? I really don't like the idea of manually measuring the height of the list elements and it apparently doesn't work but why can't android nicely stretch the ListView inside the ScrollView to fit it all in there?
Clipped list:
Use this method created by https://stackoverflow.com/users/205192/dougw
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
It's a BAD practice to encapsulate ListView within a ScrollView because ListView itself contains scrolling capabilities. You should implement a solution that does not contain such hierarchy of views and I hope it will do the magic :)
Here resource of main layout with ScrollView:
<ScrollView android:layout_height="fill_parent" android:layout_width="fill_parent">
<LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="#+id/parentLayout"/>
</ScrollView>
Here the code to insert items:
parentLayout.removeAllViews();
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
for (int i = comments.size() - 1; i >= 0; i--) {
CommentInfo comment = comments.get(i);
View view = inflater.inflate(your_resource_id, null, false);
TextView commentsContent =(TextView)view.findViewById(R.id.commentContent);
if (commentsContent != null) {
String data = String.format("%s (by %s, %s)", comment.getCommentText(), comment.getUserName(),
commentsContent.setTextSize(st.getTextSize());
commentsContent.setText(data);
}
parentLayout.addView(view, 0);
}
I had the same problem in my project.You need to create simple LinearLayout inside ScrollView. After that you need create new View with your listview item xml using LayoutInflater. After creation put all data in new View and add to LinearLayout as child view:
linearLayot.addView(newView, position_you_need).
Hope it would help you!
I took the recommendation of not using a ListView element inside a ScrollView to heart and decided to use a slightly brute force method to achieve what I need. Since there is a constant number of up to five list rows that need to be displayed I removed the ListView instantiation from the xml file and replaced it with five instances of rows:
<include android:id="#+id/info_comment_1" layout="#layout/chat_single_message" />
<include android:id="#+id/info_comment_2" layout="#layout/chat_single_message" />
<include android:id="#+id/info_comment_3" layout="#layout/chat_single_message" />
<include android:id="#+id/info_comment_4" layout="#layout/chat_single_message" />
<include android:id="#+id/info_comment_5" layout="#layout/chat_single_message" />
In the Activity class I declare five placeholders for these views:
private RelativeLayout mChatMessages[] = new RelativeLayout[COMMENTS_NUMBER];
and initialize them with:
mChatMessages[0] = (RelativeLayout) mMoreInfoLayout.findViewById(R.id.info_comment_1);
mChatMessages[1] = (RelativeLayout) mMoreInfoLayout.findViewById(R.id.info_comment_2);
mChatMessages[2] = (RelativeLayout) mMoreInfoLayout.findViewById(R.id.info_comment_3);
mChatMessages[3] = (RelativeLayout) mMoreInfoLayout.findViewById(R.id.info_comment_4);
mChatMessages[4] = (RelativeLayout) mMoreInfoLayout.findViewById(R.id.info_comment_5);
Then, whenever a new message is received I use the ChatAdapter (the same I used for the ListView previously) and call its getView() method:
protected void updateChatMessages() {
int msgCount = mChatAdapter.getCount();
for (int i = 0; i < COMMENTS_NUMBER; i++) {
if (msgCount <= i) {
mChatMessages[i].setVisibility(View.GONE);
} else {
mChatMessages[i] = (RelativeLayout) mChatAdapter.getView(i, mChatMessages[i], null);
mChatMessages[i].setVisibility(View.VISIBLE);
}
}
}
I don't inflate the pariculat views ever again since the only thing that changes is the content of each row, not the layout. This means there is no performance penalty here.
This is basically a manual implementation of a ListView with a limited maximum number of elements. This time, however, ScrollView is able to fit them nicely and nothing gets clipped.
For a dynamic number of rows the approach suggested by Layko could be employed with the views being instantiated programatically and added to the LinearLayout inside the ScrollView.
I can see the ListView is inside a ViewPager; one other simple approach to resolving this issue is to add
app:layout_behavior="#string/appbar_scrolling_view_behavior" to the ViewPager in your layout xml as seen below.
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
To prevent the same behavior at the bottom of the list, you can also add android:layout_marginBottom="?attr/actionBarSize" to the ViewPager like so
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:layout_marginBottom="?attr/actionBarSize"/>
This is coming late, but I hope it helps any other person.
try it..
after create all view add bellow line for ScrollView location on screen (x,y)
ScrollView scrollView = (ScrollView)findViewById(R.id.scrollView);
scrollView.smoothScrollTo(0,0);// top location zero index
I had a similar problem. I have a
RelativeLayout
listView
includeLayout
where I include some bottom nav beneath the listView with this
<include
android:id="#+id/includeLayout"
layout="#layout/bottom_nav_bar"
and my listView was clipped - not taking the full height available between the header and bottom nav. I tried various xml settings suggested in this and other threads, but what worked for me was to add
android:layout_alignBottom="#+id/includeLayout"
to my listView. That seemed to pull the listView down to the top of the bottom nav, so that the listView is now using the full available height (and it scrolls as needed).
This works for me
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="#dimen/activity_vertical_margin">
<TextView
android:id="#+id/tv_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="17sp"
android:text="#string/text_list_devices" />
<ListView
android:id="#+id/lv_paired"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/activity_vertical_margin"
android:cacheColorHint="#00000000"
android:layout_above="#+id/signup_t"
android:layout_below="#id/tv_status"
/>
<Button
android:id="#+id/signup_t"
style="?android:textAppearanceSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:textColor="#android:color/white"
android:layout_alignParentBottom="true"
android:text="Print All Records"
android:typeface="sans"
android:layout_marginLeft="45dp"
android:layout_marginRight="45dp"
android:textSize="24sp"
android:background="#drawable/selector_for_button"
android:textStyle="bold" />
</RelativeLayout>
This is BAD practice. But there are some situations we can not avoid using that. For example dynamic e-commerce layouts we may put multiple lists or recycle views but you don't want to scroll inside a single item height (if accidentally wanted!!). I faced this kind of problem. I fixed using a simple way. I don't tell this is the correct way but it may help some.
!! I used to recycle the view.
(01) Create an Interface to return view height.
public interface AfterViewLoadListener {
void onViewHeightMeasured(int height, String mode);
}
(02) implement with your activity
public class *Activity extends AppCompatActivity implements AfterViewLoadListener{
/** your codes **/
final SimpleListRecycleAdapter order_adapter = new SimpleListRecycleAdapter(this,"ORDER");
}
#Override
public void onViewHeightMeasured(int height, String mode) {
if(mode.equals("ORDER") && height > 0){
recycleView.setMinimumHeight(height);
}
}
(03) inside the recycle view custom adapter
AfterViewLoadListener viewLoadListener = null;
public SimpleListRecycleAdapter(AfterViewLoadListener listener, String mode) {
if(listener instanceof AfterViewLoadListener){
viewLoadListener = listener;
}
this.mode = mode;
}
(04) override the onViewAttachedToWindow method
#Override
public void onViewAttachedToWindow(#NonNull SimpleListViewHolder holder) {
super.onViewAttachedToWindow(holder);
View view = holder.itemView;
view.measure(0, 0);
this.viewMinHeight = view.getMeasuredHeight();
if(!firstFlag){
firstFlag = true;
viewLoadListener.onViewHeightMeasured(this.viewMinHeight*filtered.length(),mode);
}
}
(05) That's it. It worked for me.