I have created an app with a bottom sheet that utilizes bottom sheets with a list view.
Previously, I have used a recyclerView
to show the list items from an array list, inside the bottom sheet. Now, I have changed the app to use a listView
instead, by retrieving data from a cursor.
Now, the bottom sheet only shows a single item:
Even in the android studio preview, I can only see 1 list item:
I have created a test activity with a single list view, and all the data is shown except for the fact that every 3rd item is "distorted".
Here is the code for the Layout Activity:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/coordinateLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="0dp"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:paddingTop="0dp"
tools:context=".MainActivity"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="EventList Button"
android:id="@+id/eventlistbutton"
android:layout_alignParentBottom="true"
/>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/contactsbutton"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_margin="12dp"
android:id="@+id/contactsbutton"
android:clickable="true"
app:backgroundTint="@color/cardbackground2"
app:fabSize="normal"
/>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/zoomunpressed"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_margin="12dp"
android:id="@+id/zoomOut"
android:clickable="true"
app:backgroundTint="@color/cardbackground2"
app:fabSize="normal"
app:borderWidth="-120000dp"
/>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/zoom2unpressed"
android:id="@+id/zoomIn"
android:clickable="true"
app:backgroundTint="@color/cardbackground2"
app:fabSize="normal"
app:borderWidth="-120000dp"
app:layout_anchor="@id/zoomOut"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_below="@+id/zoomOut"
/>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/messageunpressed"
android:id="@+id/chatbutton"
android:clickable="true"
app:backgroundTint="@color/cardbackground2"
app:fabSize="normal"
android:layout_marginRight="12dp"
android:layout_below="@+id/contactsbutton"
android:layout_alignStart="@+id/contactsbutton" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/bottom_sheet_behavior"
android:clipToPadding="true"
android:orientation="vertical"
android:id="@+id/bottomsheet"
>
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/cardbackground"
android:gravity="center"
android:text="Event List"
android:textColor="@color/white"
android:textStyle="bold"
android:textSize="18sp"
/>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="9"
android:background="@color/recyclerview_background"
>
<ListView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/eventlistview"
android:paddingLeft="@dimen/recyclerviewhorizontalpadding"
android:paddingRight="@dimen/recyclerviewhorizontalpadding"
>
</ListView>
</android.support.v4.widget.NestedScrollView>
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
Here is the code for the Listview items:
<android.support.v7.widget.CardView
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:id="@+id/CardViewItem"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardBackgroundColor="@color/cardbackground2"
card_view:cardCornerRadius="@dimen/cardviewcorner"
card_view:cardElevation="8dp"
>
<!--android:layout_marginTop="8dp"-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/cardbackground"
android:orientation="horizontal"
>
<TextView
android:id="@+id/event_name"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:padding="@dimen/cardmargin"
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="bold"
tools:text="Museum Tour"
/>
<TextView
android:id="@+id/event_date"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:padding="@dimen/cardmargin"
android:textAlignment="viewEnd"
android:textColor="@color/white"
android:textSize="18dp"
android:textStyle="bold"
tools:text="8/24"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/card_view_height"
android:background="@color/cardbackground2"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
>
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:paddingLeft="@dimen/cardmargin"
android:textColor="@color/white"
android:textSize="18sp"
android:text="Time:"
android:textStyle="bold"
/>
<TextView
android:id="@+id/event_time"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginRight="18dp"
android:layout_weight="3"
android:gravity="center_vertical"
android:paddingLeft="@dimen/cardmargin"
android:textAlignment="textEnd"
android:textColor="@color/white"
android:textSize="18sp"
tools:text="11:50"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:clickable="true"
android:gravity="center_vertical"
android:paddingLeft="@dimen/cardmargin"
android:textColor="@color/white"
android:textSize="18sp"
android:text="Summary:"
android:textStyle="bold"
/>
<TextView
android:id="@+id/event_summary"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:clickable="true"
android:ellipsize="end"
android:gravity="center_vertical"
android:maxLength="130"
android:maxLines="1"
android:paddingLeft="@dimen/cardmargin"
android:layout_marginRight="18dp"
android:text="Once upon a time a few missadfsafasdfasfdf"
android:textColor="@color/white"
android:textSize="18sp"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:clickable="true"
android:gravity="center_vertical"
android:paddingLeft="@dimen/cardmargin"
android:textColor="@color/white"
android:textSize="18sp"
android:text="Participants:"
android:textStyle="bold"
/>
<TextView
android:id="@+id/event_participantNum"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:clickable="true"
android:gravity="center_vertical"
android:paddingLeft="@dimen/cardmargin"
android:layout_marginRight="18dp"
android:text="80"
android:textAlignment="viewEnd"
android:textColor="@color/white"
android:textSize="18sp"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:clickable="true"
android:gravity="center_vertical"
android:paddingLeft="@dimen/cardmargin"
android:textColor="@color/white"
android:textSize="18sp"
android:text="Location:"
android:textStyle="bold"
/>
<TextView
android:id="@+id/event_location"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:clickable="true"
android:gravity="center_vertical"
android:paddingLeft="@dimen/cardmargin"
android:layout_marginRight="18dp"
android:text="Rio de Janeiro"
android:textAlignment="viewEnd"
android:textColor="@color/white"
android:textSize="18sp"
/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
Finally, here is the code for the Main Activity:
public class MainActivity extends FragmentActivity implements OnMapReadyCallback {
Button eventListButton;
public static BottomSheetBehavior mBottomsheetbehvior;
RecyclerView rv;
LinearLayoutManager llm;
Context context;
public static GoogleMap mMap;
FloatingActionButton contactsbutton;
FloatingActionButton testButton;
Intent contactsintent;
Intent testIntent;
DatabaseHelper eventsDBHelper;
EventListCursorAdapter eventListCursorAdapter;
Cursor eventCursor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myDataHolder dataHolder = new myDataHolder();
context = this;
eventsDBHelper = new DatabaseHelper(context);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
LinearLayout bottomsheet =
findViewById(R.id.bottomsheet);
mBottomsheetbehvior = BottomSheetBehavior.from(bottomsheet);
mBottomsheetbehvior.setHideable(true);
mBottomsheetbehvior.setPeekHeight(400);
mBottomsheetbehvior.setState(BottomSheetBehavior.STATE_HIDDEN);
eventListButton = findViewById(R.id.eventlistbutton);
eventListButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(mBottomsheetbehvior.getState() == BottomSheetBehavior.STATE_EXPANDED) {
mBottomsheetbehvior.setState(BottomSheetBehavior.STATE_COLLAPSED);
eventListButton.setText("Hide");
}
else if(mBottomsheetbehvior.getState() == BottomSheetBehavior.STATE_COLLAPSED) {
mBottomsheetbehvior.setState(BottomSheetBehavior.STATE_HIDDEN);
eventListButton.setText("Event List Button");
}
else if(mBottomsheetbehvior.getState() == BottomSheetBehavior.STATE_HIDDEN) {
mBottomsheetbehvior.setState(BottomSheetBehavior.STATE_EXPANDED);
eventListButton.setText("Peek");
}
}
});
mBottomsheetbehvior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_EXPANDED) {
eventListButton.setText("Peek");
}
else if (newState == BottomSheetBehavior.STATE_COLLAPSED) {
eventListButton.setText("Hide");
}
else if (newState == BottomSheetBehavior.STATE_HIDDEN) {
eventListButton.setText("Event List Button");
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
final ListView eventListView = (ListView) findViewById(R.id.eventlistview);
final DatabaseHelper eventManager = new DatabaseHelper(context);
Thread thread = new Thread(new Runnable(){
@Override
public void run(){
eventCursor = eventManager.getAllEvents();
eventListCursorAdapter = new EventListCursorAdapter(
MainActivity.this,
eventCursor,
0);
eventListView.setAdapter(eventListCursorAdapter);
}
});
thread.start();
}
@Override
public void onMapReady(GoogleMap googleMap) {
//Stuff
}
public void moveCamera(LatLng location){
final CameraPosition movelocation = CameraPosition.builder().
target(location).zoom(14).build();
MainActivity.mMap.animateCamera(CameraUpdateFactory.newCameraPosition(movelocation));
}
}
If it helps, here is the code for the cursor adapter:
public class EventListCursorAdapter extends CursorAdapter {
private LayoutInflater cursorInflater;
Calculations calculations = new Calculations();
Gson gson = new Gson();
Context AppContext;
public EventListCursorAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
cursorInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
AppContext = context.getApplicationContext();
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return cursorInflater.inflate(R.layout.card_view, parent, false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
TextView timeText = (TextView) view.findViewById(R.id.event_time);
TextView nameText = (TextView) view.findViewById(R.id.event_name);
TextView dateText = (TextView) view.findViewById(R.id.event_date);
TextView summaryText = (TextView) view.findViewById(R.id.event_summary);
TextView participantsText = (TextView) view.findViewById(R.id.event_participantNum);
TextView locationText = (TextView) view.findViewById(R.id.event_location);
final Cursor mCursor = cursor;
String date = calculations.UnixTimeConverter(
mCursor.getLong(mCursor.getColumnIndex(DatabaseHelper.COL_UNIXTIME)
))[0];
String time = calculations.UnixTimeConverter(
mCursor.getLong(mCursor.getColumnIndex(DatabaseHelper.COL_UNIXTIME))
)[1];
final LatLng location = gson.fromJson(mCursor.getString(mCursor.getColumnIndex(DatabaseHelper.COL_LOCATION)),LatLng.class);
nameText.setText(mCursor.getString(mCursor.getColumnIndex(DatabaseHelper.COL_NAME)));
dateText.setText(date);
timeText.setText(time);
participantsText.setText(mCursor.getInt(mCursor.getColumnIndex(DatabaseHelper.COL_PARTICIPANTS))+"");
summaryText.setText(mCursor.getString(mCursor.getColumnIndex(DatabaseHelper.COL_SUMMARY)));
locationText.setText(mCursor.getString(mCursor.getColumnIndex(DatabaseHelper.COL_LOCATIONNAME)));
locationText.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
final CameraPosition camLocation = CameraPosition.builder().
target(location).zoom(18).build();
MainActivity.mMap.animateCamera(CameraUpdateFactory.newCameraPosition(camLocation));
}
});
summaryText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
LayoutInflater mLayoutInflator;
mLayoutInflator = LayoutInflater.from(AppContext);
final AlertDialog.Builder mBuilder = new AlertDialog.Builder(mContext);
View mView = mLayoutInflator.inflate(R.layout.summarydialog,null);
TextView textView = mView.findViewById(R.id.mainText);
textView.setText(
mCursor.getString(mCursor.getColumnIndex(DatabaseHelper.COL_SUMMARY))
);
textView.setMovementMethod(new ScrollingMovementMethod());
mBuilder.setView(mView);
final AlertDialog dialog = mBuilder.create();
dialog.show();
}
});
}
}
It will be helpful if you could tell how to have the bottom sheet listview show all of the data in the cursor, without having some of the list items being "distorted" like in the second image
I have found the solution. Just remove the Nested ScrollView tag. Apparently, you are not supposed to put a ListView inside of a scrollview
It will not cause any kind of behavorial changes to the bottom sheet :)