I have a project i am developing but i have come to face a problem with a large gap appearing between two items on my android application ,i had tried to look on every previous suggestions here on how to solve the problem but none has worked for me
Here is my Layout that causes problems
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:layout_height="match_parent"
android:orientation="horizontal">
<android.support.v7.widget.RecyclerView
android:id="#+id/prodct_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="false"
android:scaleType="fitXY"
android:padding="0dp"
android:adjustViewBounds="true"/>
<android.support.design.widget.FloatingActionButton
android:id="#+id/actionbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_gravity="end"
android:visibility="gone" />
And here is my oncreate method on activity associated with the above layout:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tabletSize = getResources().getBoolean(R.bool.isTablet);
if (!tabletSize) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
setContentView(R.layout.order_details);
ab = getSupportActionBar();
ab.setDisplayUseLogoEnabled(true);
ab.setDisplayHomeAsUpEnabled(true);
actionButton = (FloatingActionButton) findViewById(R.id.actionbutton);
actionButton.setBackgroundColor(getResources().getColor(R.color.actionbar));
actionButton.setImageResource(R.drawable.ic_action_send);
appPreference = new AppPreference(this);
mRecyclerView = (RecyclerView) findViewById(R.id.prodct_list);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
final Intent intent = getIntent();
pyid = intent.getExtras().getLong(Quotes.ID);
mItemsDetail = QuoteItems.getItemsArray(this ,pyid);
mAdapter = new DeliveryDetailsAdapter(this, mItemsDetail);
mRecyclerView.setAdapter(mAdapter);
pContent = new ParseContent(this);
title = intent.getExtras().getString(Quotes.REFERENCE);
if (pyid == 0)
finish();
if (Validating.areSet(title))
ab.setTitle("Quote Details");
else
ab.setTitle(getString(R.string.strorder));
mRecyclerView.addOnItemTouchListener(
new RecylerItemClick(this, new RecylerItemClick.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
}
})
);
And here is my list of items populated on recyclerview:
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_view11"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/rltotals"
android:layout_below="#+id/autotxtsaleclientname"
card_view:cardBackgroundColor="#color/white"
card_view:cardCornerRadius="7.0dip"
card_view:cardElevation="0dp">
<android.support.v7.widget.RecyclerView
android:id="#+id/prodct_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:scrollbars="vertical" />
</android.support.v7.widget.CardView>
And when i run the application on that part the items on recyclerview displays with large gap between each item
Can anyone help me to solve the issue with the gap between the items
The problem is with your adapter class. You need to make the adapter class parent height as wrap_content. Since your recylerview is vertical, you need to change the height of the adapter parent layout to wrap_content. After that also if the problem exists check whether any other adapter child view height is match_parent, if so change that to wrap_content.
Hope this is Helpful :)
check the item layout inside DeliveryDetailsAdapter for inflating each item (OncreateViewholder)
You may have given some margin in root layout. remove margin from root layout and set width as match parent and height as wrap_content
Related
I have Implemented a RecyclerView with GridLayoutManager which has both Vertical and Horizontal Scroll , I need to scroll the layout to particular position , referred many codes but it did'nt worked out for me .
Java Class code :
void RackGen()
{
STRarray = (String[]) mStringList.toArray(new String[mStringList.size()]);
ROWarray = (String[]) mRowList.toArray(new String[mRowList.size()]);
numcol = Integer.parseInt(col);
numdata = Integer.parseInt(num);
rv = (RecyclerView) findViewById(R.id.rview);
int numberOfColumns = numcol;
GridLayoutManager GM2 = new GridLayoutManager(this,numberOfColumns);
rv.setLayoutManager(GM2);
rv.setNestedScrollingEnabled(true);
rv.setHasFixedSize(true);
adapter = new MyRecyclerViewAdapter(this, STRarray, ROWarray);
rv.setAdapter(adapter);
XML :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="20dp"
android:layout_centerHorizontal="true"
android:id="#+id/llzoom"
android:orientation="vertical"
>
<android.support.v4.widget.NestedScrollView
android:id="#+id/nested_scroll_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android">
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scrollbars="none"
android:overScrollMode="never">
<android.support.v7.widget.RecyclerView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/rview">
</android.support.v7.widget.RecyclerView>
</HorizontalScrollView>
</ScrollView>
</android.support.v4.widget.NestedScrollView>
</LinearLayout>
Only after adding nested scroll view along with vertical and horizontal scroll , scrolling worked smoothly on both directions . Now i need to scroll to particular position.
Thank You
You need to reference to your NestedScrollView inside your activity and then call the scrollTo(x,y) on that object, example:
NestedScrollView nestedScrollView = (NestedScrollView) findViewById(R.id.nested_scroll_view);
nestedScrollView.scrollTo(x,y);
x and y are horizontal and vertical scrolls.
I know this is an older post, and I haven't tested this code on nested scroll views, but as you only have one position value, you can try this technique.
This works great for scrolling to the currently selected view of a recyclerview GridLayoutManager with dynamic autofit (I use a custom recyclerview for autofit, not the grid itself).
After I set the adapter:
recyclerView.setAdapter(adapter);
I put (just under it in onCreate):
recyclerView.post(new Runnable()
{
#Override
public void run()
{
layoutManager.scrollToPositionWithOffset(currentSelected, 0);
}
});
It waits for the views to be drawn, then it scrolls to the position given. It works wonderfully!
I got the idea here: https://stackoverflow.com/a/52895262/2905354
I have a RecyclerView which im using to display messages, in a text app type way. By that I mean, new messages added to the RecyclerView should appear on the bottom.
Currently, im using .setStackFromEnd(true) on my LinearLayoutManager to make messages appear starting from the bottom:
layMng = new LinearLayoutManager(this);
layMng.setStackFromEnd(true);
mRecyclerView.setLayoutManager(layMng);
mRecyclerView.setAdapter(mAdapter);
What happens is, when enough messages are received and the list of messages is about to overflow past the top of the screen, it stops always showing the new messages at the bottom. I have to scroll down manually to see the new additions.
How can I get it to either always have the newest message be viewable or have the RecyclerView scroll down when a new item is received?
I tried various methods on my layout manager like .scrollToPosition() and .scrollToPositionWithOffset() but none of the suggestions i've seen so far have worked. A few of the top StackOverflow questions on the issue have top answers that dont even solve the original question..
So how is this done?
Please check layout_height. It should be android:layout_height="match_parent"
Run smoothScrollToPosition in UI thread
code snippet from my code
<android.support.v7.widget.RecyclerView
android:id="#+id/topic_screen_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="18dp"
/>
//here topicScreenList is referencing my Recylerview:
//-messageAdapter: referencing adpapter object
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
layoutManager.setStackFromEnd(true);
topicScreenList.setLayoutManager(layoutManager);
topicScreenList.setAdapter(messageAdapter);
}
after getting any new messages, following code gets called from backend service
-Here MessageItem is referencing new Message item consumed by adapter
#Override
public void onNewMessage(final MessageItem messageItem) {
if (getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
messageAdapter.addMessageToEnd(messageItem);
topicScreenList.smoothScrollToPosition(messageAdapter.getItemCount());
}
});
}
}
//code from my Adapter
public void addMessageToEnd(MessageItem messageItem) {
messageItems.add(messageItem);
notifyItemInserted(messageItems.size() -1);
}
Try this, Am also developing a chat application, and it works perfectly for me
mRecyclerView.setAdapter(adaptorChat);
mRecyclerView.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
llm.setStackFromEnd(true);
mRecyclerView.setLayoutManager(llm);
XML
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/messages_list_sponsor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/edit_compose_msg_container" />
<LinearLayout
android:id="#+id/edit_compose_msg_container"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:orientation="horizontal"
android:padding="3dp">
<EditText
android:id="#+id/compose_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:layout_weight="1"
android:background="#drawable/white_edit_text_style"
android:hint="#string/enter_message"
android:inputType="textMultiLine"
android:minHeight="50dp"
android:paddingEnd="4dp"
android:paddingLeft="6dp"
android:paddingRight="4dp"
android:paddingStart="6dp"
android:singleLine="false"
android:textColor="#color/black"
android:textColorHint="#android:color/darker_gray" />
<ImageView
android:id="#+id/send_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="5"
android:clickable="true"
android:padding="15dp"
android:rotation="-35"
android:layout_marginBottom="5dp"
android:src="#drawable/message_send" />
</LinearLayout>
</RelativeLayout>
mRecyclerView.scrollToPosition(position); should work. It could be that it's trying to scroll before the position/adapter is updated. Try:
int delay = 500;
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
//scroll to bottom
mRecyclerView.smoothScrollToPosition(mAdapter.getItemCount());
}
}, delay);
if you have set mRecyclerView.setNestedScrollingEnabled(false) then remove this.
Goodd day.I have simple recycler view with simplest dummy datas for test purpose,thus i have an weird issue to which the google did not find any solution or even an issue at all.On first launch the view is all good but as soon as i start to scrool,the child items are being as far from each other as no one can image...Really very and very far.But the issue is that the actual child items layout parameters are correct,only issue is that i dont know why RecyclerView decides to have each item heaps far away from each other.Please can you give me an help?Posting full code of my RecyclerView.
The view for recyclerView
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.ink.activities.HomeActivity"
tools:showIn="#layout/app_bar_home">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical" />
</RelativeLayout>
The Adapter.
public class FeedAdapter extends RecyclerView.Adapter<FeedAdapter.ViewHolder> {
private List<FeedModel> feedList;
private Context mContext;
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView title, content;
public ViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.feedTitle);
content = (TextView) view.findViewById(R.id.feedContent);
}
}
public FeedAdapter(List<FeedModel> feedList, Context context) {
mContext = context;
this.feedList = feedList;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.feed_single_view, parent, false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
FeedModel feedModel = feedList.get(position);
holder.title.setText(feedModel.getTitle());
holder.content.setText(feedModel.getContent());
// animate(holder);
}
public void animate(RecyclerView.ViewHolder viewHolder) {
final Animation animAnticipateOvershoot = AnimationUtils.loadAnimation(mContext, R.anim.bounce_interpolator);
viewHolder.itemView.setAnimation(animAnticipateOvershoot);
}
#Override
public int getItemCount() {
return feedList.size();
}
}
I guess you won`t need holder as no view initiated with it.
The single child item view of RecyclerView adapter.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground"
app:cardCornerRadius="5dp"
app:cardElevation="10dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/feedTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:fontFamily="#string/appFont"
android:text="loading...."
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:id="#+id/feedContent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/feedTitle"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp"
android:layout_marginTop="10dp" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
The initiation of actual parameters.
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mAdapter = new FeedAdapter(mFeedModelArrayList, this);
RecyclerView.ItemAnimator itemAnimator = new DefaultItemAnimator();
itemAnimator.setAddDuration(500);
itemAnimator.setRemoveDuration(500);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setItemAnimator(itemAnimator);
This code is as simple as it can get and it is important to mention that i am initiation all this inside the default NAVIGATION DRAWER ACTIVITY of android studio (the default templae inside content_main layout).So plaese can you give me any hint about the issue?
You're using
android:layout_width="match_parent"
android:layout_height="match_parent"
on your child item views. As of Support Library 23.2:
The RecyclerView widget provides an advanced and flexible base for creating lists and grids as well as supporting animations. This release brings an exciting new feature to the LayoutManager API: auto-measurement! This allows a RecyclerView to size itself based on the size of its contents. This means that previously unavailable scenarios, such as using WRAP_CONTENT for a dimension of the RecyclerView, are now possible. You’ll find all built in LayoutManagers now support auto-measurement.
Due to this change, make sure to double check the layout parameters of your item views: previously ignored layout parameters (such as MATCH_PARENT in the scroll direction) will now be fully respected.
Change your layout_height to wrap_content if you only want your items to be as large as needed. match_parent means they will be as large as the screen.
I'm trying to make a chat-like screen with RecyclerView as this
However RecyclerView (LinearLayoutManager) doesn't works as I expected...
How can I fix or avoid this problem?
Detail:
The problem is also reproducible with very simplified Activity shown below.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"
android:scrollbars="none"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeRecyclerView();
}
private void initializeRecyclerView() {
RecyclerView recycler = (RecyclerView) findViewById(R.id.recyclerview);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setReverseLayout(true);
recycler.setLayoutManager(layoutManager);
Adapter recyclerAdapter = new Adapter(createItemList());
recycler.setAdapter(recyclerAdapter);
}
private static ArrayList<String> createItemList(){
ArrayList<String> items= new ArrayList<>();
for(int i=0;i<20;i++){
items.add(String.format("item %02d",20-i));
}
return items;
}
}
RecyclerView is not completely relayout after IME candidates are hidden shown in this movie.
This problem is fixed by adding "adjustResize" into MainActivity's windowSoftInputMode, but I don't want to use it. Solution without changing windowSoftInputMode is wanted.
I had a similar problem. What will help you is creating a custom adapter which has a different viewholder and onbindview for the IME candidates. Then you can easily hide the IME candidates by changing LayoutView.Params and setting height to zero. This is how I've done it, sounds like a workaround but works for me. Hope this helps.
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.