Layout issue when large amount of data present
We have a layout issue on the last element of the LIST
It only occurs when the list is populated with a large number of items.
In this case the height of the last element is to narrow to display it's content.
Can this issue be fixed ?
Hm. Curious. How many items is "large"?
Is there anything special about your last item?
I'd have to take a look at your XML to make any further guesses. Can you post? DSLV and item layout preferably. Thanks!
Also. Do things work correctly in a regular ListView?
I don't see your code. Are you sure you sent it?
Drat, I still don't see your code. Are you pasting directly into a GitHub comment box?
package be.test.view.settings;
import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView;
import be.test.android.R; import be.test.android.model.IProduct; import be.test.android.presenter.settings.products.ProductVisibility; import be.test.android.util.AlertDialogHelper; import be.test.android.util.MetricHelper; import be.test.android.util.TypefaceHelper; import be.test.android.util.TypefaceManager.TypefaceName; import be.test.android.view.AbstractLinearLayout; import be.test.android.view.settings.DragSortListView.DropListener; import be.test.android.widget.Switch;
import java.util.ArrayList; import java.util.List;
public class ProductsListView extends AbstractLinearLayout {
private final DragSortListView mListView;
private final TextView mTitleLabel;
private ProductAdapter mAdapter;
private boolean mHasChanged;
private boolean mShouldHaveAtLeastOneSelected;
public ProductsListView(Context context, SettingsProductOrderView parent) {
super(context);
setContentView(R.layout.settings_product_order_list);
setOrientation(VERTICAL);
setClipToPadding(false);
setPadding(toDp(8), toDp(8), toDp(8), toDp(8));
mTitleLabel = (TextView) findViewById(R.id.titleLabel);
mListView = (DragSortListView) findViewById(android.R.id.list);
TypefaceHelper.applyTypeface(TypefaceName.ROBOTO_REGULAR, mTitleLabel);
}
private DropListener mDropListener = new DropListener() {
@Override
public void drop(int from, int to) {
mAdapter.moveData(from, to);
mAdapter.notifyDataSetChanged();
mHasChanged = true;
}
};
public void setTitle(String title) {
mTitleLabel.setText(title);
}
public void setShouldHaveAtLeastOneSelected(boolean atLeastOne) {
mShouldHaveAtLeastOneSelected = atLeastOne;
}
public void setProducts(List<ProductVisibility> products) {
ArrayList<ProductVisibility> mProducts = new ArrayList<ProductVisibility>(products);
mAdapter = new ProductAdapter(mProducts);
mListView.setAdapter(mAdapter);
int rowHeight = getContext().getResources().getDimensionPixelSize(
R.dimen.settings_product_item_height);
int height = rowHeight * mProducts.size()
+ MetricHelper.dpToPixel(getContext(), 10);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, height);
mListView.setLayoutParams(layoutParams);
}
public List<ProductVisibility> getProductsVisibility() {
return mAdapter.getData();
}
public void setEditOrderMode(boolean editOrderMode) {
mAdapter.setShowDrag(editOrderMode);
mListView.setDropListener(editOrderMode ? mDropListener : null);
mAdapter.notifyDataSetChanged();
}
public boolean canStillDeselectProduct() {
if (!mShouldHaveAtLeastOneSelected)
return true;
int nb = 0;
for (ProductVisibility pv : mAdapter.getData()) {
nb += pv.isVisible() ? 1 : 0;
}
return nb > 1;
}
public boolean hasChanged() {
return mHasChanged;
}
private class ProductAdapter extends BaseAdapter {
private boolean mShowDrag;
private List<ProductVisibility> data;
public ProductAdapter(List<ProductVisibility> data) {
this.data = data;
}
public void moveData(int from, int to) {
ProductVisibility ProductVisibilityFrom = this.data.get(from);
data.remove(ProductVisibilityFrom);
data.add(to, ProductVisibilityFrom);
}
public List<ProductVisibility> getData() {
return data;
}
@Override
public Object getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getCount() {
return data.size();
}
public void setShowDrag(boolean flag) {
mShowDrag = flag;
}
public boolean isLast(int position) {
return position == getCount() - 1;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//re-use of convertView removed because of problem when reuse of listeners
convertView = View.inflate(getContext(),R.layout.settings_product_order_list_item, null);
ProductVisibility productVisibility = (ProductVisibility) getItem(position);
IProduct product = productVisibility.getProduct();
TextView mTypeLabel = (TextView)convertView.findViewById(R.id.typeLabel);
TextView mNameLabel = (TextView)convertView.findViewById(R.id.nameLabel);
TextView mNumberLabel = (TextView)convertView.findViewById(R.id.numberLabel);
Switch mOnOffSwitch =(Switch) convertView.findViewById(R.id.toggle);
ImageView mDrag = (ImageView)convertView.findViewById(R.id.drag);
View mSeparator = convertView.findViewById(R.id.separator);
mTypeLabel.setText(product.getDescription());
mNameLabel.setText(product.getNameHolder());
mNumberLabel.setText(product.getProductNumber());
mOnOffSwitch.setChecked(productVisibility.isVisible());
mOnOffSwitch.setVisibility(mShowDrag ? View.GONE : View.VISIBLE);
mDrag.setVisibility(mShowDrag ? View.VISIBLE : View.GONE);
mSeparator.setVisibility(!isLast(position) ? View.VISIBLE: View.GONE);
//Can't resuse this listener via inflation
mOnOffSwitch.setOnCheckedChangeListener(new SwitchOnCheckListener(productVisibility));
TypefaceHelper.applyTypeface(TypefaceName.ROBOTO_REGULAR, mOnOffSwitch);
TypefaceHelper.applyTypeface(TypefaceName.ROBOTO_REGULAR, mTypeLabel);
TypefaceHelper.applyTypeface(TypefaceName.ROBOTO_REGULAR, mNameLabel);
TypefaceHelper.applyTypeface(TypefaceName.ROBOTO_REGULAR, mNumberLabel);
return convertView;
}
private void showAlertLastProductUnchecked() {
AlertDialogHelper
.getBuilder(getContext())
.setTitle("")
.setMessage(R.string.a24_error_minimum_account_message)
.setPositiveButton(
R.string.a24_error_minimum_account_button_label,
null).show();
}
private class SwitchOnCheckListener implements OnCheckedChangeListener{
private ProductVisibility productVisibility;
public SwitchOnCheckListener(ProductVisibility productVisibility){
this.productVisibility=productVisibility;
}
@Override
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
if (isChecked) {
productVisibility.setVisible(true);
mHasChanged = true;
} else {
if (canStillDeselectProduct()) {
productVisibility.setVisible(false);
mHasChanged = true;
} else {
buttonView.setChecked(true);
showAlertLastProductUnchecked();
}
}
}
}
}
}
and here is our xml describing a single list item
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" xmlns:test="http://schemas.android.com/apk/res/be.test.android">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="@dimen/settings_product_item_height" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/actionContainer"
android:orientation="vertical" >
<TextView
android:id="@+id/typeLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="1"
android:shadowColor="#fff"
android:shadowDy="1"
android:shadowRadius="1"
android:text="BLUE REKENING"
android:textAllCaps="true"
android:textColor="#78736E" />
<TextView
android:id="@+id/nameLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="1"
android:shadowColor="#fff"
android:shadowDy="1"
android:shadowRadius="1"
android:text="Sterck & co bvba"
android:textColor="#51626F" />
<TextView
android:id="@+id/numberLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="1"
android:shadowColor="#fff"
android:shadowDy="1"
android:shadowRadius="1"
android:text="BE1234567890"
android:textColor="#78736E" />
</LinearLayout>
<RelativeLayout
android:id="@+id/actionContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" >
<be.test.android.widget.Switch
style="@style/Widget.Button.Switch"
android:id="@+id/toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:focusableInTouchMode="false"
android:checked="true" />
<ImageView
android:id="@+id/drag"
android:layout_width="wrap_content"
android:layout_height="60dp"
android:src="@drawable/drag_handle" />
</RelativeLayout>
</RelativeLayout>
<View android:id="@+id/separator"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#CFCFCC" />
We fixed the problem by specifying a fixed height for the separator item
<View android:id="@+id/separator" android:layout_width="match_parent" android:layout_height="3px" android:background="#CFCFCC" />
It seems that the total height of all items is not calculated correctly when specifying this in dp
Okay, thanks. Glad that worked. I will try to reproduce the issue on my end, see what went wrong.
Well it seems not to be solved. The total height of all items is calculated incorrectly. this results in a list which does not show all items .. can you please take a look at it.
Drat. Okay. Will be a few days... swamped.