Android “Top Sheet” equivalent of “Bottom Sheet”?
I am wanting to implement a "Bottom Sheet" type of layout, but with a twist where the "bottom" sheet will be a MapFragment, which won't work very well as an up/down draggable view.
I had a probably naive thought to "flip" the logic to a "Top Sheet" design, where you drag the Top Sheet up/down to show more/less of the bottom MapFragment.
ie: From this...
...to [something like] this...
Is this possible given the Support Design Tools, or will I have to roll something like this on my own?

add a comment |
I am wanting to implement a "Bottom Sheet" type of layout, but with a twist where the "bottom" sheet will be a MapFragment, which won't work very well as an up/down draggable view.
I had a probably naive thought to "flip" the logic to a "Top Sheet" design, where you drag the Top Sheet up/down to show more/less of the bottom MapFragment.
ie: From this...
...to [something like] this...
Is this possible given the Support Design Tools, or will I have to roll something like this on my own?

3
I think you are going to sign up to do a substantial amount of heavy lifting to do two things. First, to create your custom implementation. Second, to identify how your implementation conflicts with the android implementation and to defend against those scenarios. My personal opinion, the Material Design Language has been put in place to visually communicate the ways your users can expect to interact with the app. Something like this may be great as a personal endeavour for learning, but once you hit the market - you need to expect that every single person won't understand how to use your app.
– apelsoczi
Aug 22 '16 at 20:44
I ended up just adding a bottomsheet layout that has a Toolbar at its top that allows the user to drag the toolbar up. The trick is then to resize the Map as the user drags the toolbar. I can post my code if anyone is interested.
– swooby
Sep 9 '16 at 21:08
I'd like to see it @swooby, I'm trying to do something similar
– odiggity
Nov 18 '16 at 17:26
@odiggity you can check my answer, I finally made it working exactly as the BottomSheetBehavior, but from the top.
– Carlos Alberto Martínez Gadea
Nov 21 '18 at 11:17
add a comment |
I am wanting to implement a "Bottom Sheet" type of layout, but with a twist where the "bottom" sheet will be a MapFragment, which won't work very well as an up/down draggable view.
I had a probably naive thought to "flip" the logic to a "Top Sheet" design, where you drag the Top Sheet up/down to show more/less of the bottom MapFragment.
ie: From this...
...to [something like] this...
Is this possible given the Support Design Tools, or will I have to roll something like this on my own?

I am wanting to implement a "Bottom Sheet" type of layout, but with a twist where the "bottom" sheet will be a MapFragment, which won't work very well as an up/down draggable view.
I had a probably naive thought to "flip" the logic to a "Top Sheet" design, where you drag the Top Sheet up/down to show more/less of the bottom MapFragment.
ie: From this...
...to [something like] this...
Is this possible given the Support Design Tools, or will I have to roll something like this on my own?


asked Aug 22 '16 at 20:34
swoobyswooby
1,7712431
1,7712431
3
I think you are going to sign up to do a substantial amount of heavy lifting to do two things. First, to create your custom implementation. Second, to identify how your implementation conflicts with the android implementation and to defend against those scenarios. My personal opinion, the Material Design Language has been put in place to visually communicate the ways your users can expect to interact with the app. Something like this may be great as a personal endeavour for learning, but once you hit the market - you need to expect that every single person won't understand how to use your app.
– apelsoczi
Aug 22 '16 at 20:44
I ended up just adding a bottomsheet layout that has a Toolbar at its top that allows the user to drag the toolbar up. The trick is then to resize the Map as the user drags the toolbar. I can post my code if anyone is interested.
– swooby
Sep 9 '16 at 21:08
I'd like to see it @swooby, I'm trying to do something similar
– odiggity
Nov 18 '16 at 17:26
@odiggity you can check my answer, I finally made it working exactly as the BottomSheetBehavior, but from the top.
– Carlos Alberto Martínez Gadea
Nov 21 '18 at 11:17
add a comment |
3
I think you are going to sign up to do a substantial amount of heavy lifting to do two things. First, to create your custom implementation. Second, to identify how your implementation conflicts with the android implementation and to defend against those scenarios. My personal opinion, the Material Design Language has been put in place to visually communicate the ways your users can expect to interact with the app. Something like this may be great as a personal endeavour for learning, but once you hit the market - you need to expect that every single person won't understand how to use your app.
– apelsoczi
Aug 22 '16 at 20:44
I ended up just adding a bottomsheet layout that has a Toolbar at its top that allows the user to drag the toolbar up. The trick is then to resize the Map as the user drags the toolbar. I can post my code if anyone is interested.
– swooby
Sep 9 '16 at 21:08
I'd like to see it @swooby, I'm trying to do something similar
– odiggity
Nov 18 '16 at 17:26
@odiggity you can check my answer, I finally made it working exactly as the BottomSheetBehavior, but from the top.
– Carlos Alberto Martínez Gadea
Nov 21 '18 at 11:17
3
3
I think you are going to sign up to do a substantial amount of heavy lifting to do two things. First, to create your custom implementation. Second, to identify how your implementation conflicts with the android implementation and to defend against those scenarios. My personal opinion, the Material Design Language has been put in place to visually communicate the ways your users can expect to interact with the app. Something like this may be great as a personal endeavour for learning, but once you hit the market - you need to expect that every single person won't understand how to use your app.
– apelsoczi
Aug 22 '16 at 20:44
I think you are going to sign up to do a substantial amount of heavy lifting to do two things. First, to create your custom implementation. Second, to identify how your implementation conflicts with the android implementation and to defend against those scenarios. My personal opinion, the Material Design Language has been put in place to visually communicate the ways your users can expect to interact with the app. Something like this may be great as a personal endeavour for learning, but once you hit the market - you need to expect that every single person won't understand how to use your app.
– apelsoczi
Aug 22 '16 at 20:44
I ended up just adding a bottomsheet layout that has a Toolbar at its top that allows the user to drag the toolbar up. The trick is then to resize the Map as the user drags the toolbar. I can post my code if anyone is interested.
– swooby
Sep 9 '16 at 21:08
I ended up just adding a bottomsheet layout that has a Toolbar at its top that allows the user to drag the toolbar up. The trick is then to resize the Map as the user drags the toolbar. I can post my code if anyone is interested.
– swooby
Sep 9 '16 at 21:08
I'd like to see it @swooby, I'm trying to do something similar
– odiggity
Nov 18 '16 at 17:26
I'd like to see it @swooby, I'm trying to do something similar
– odiggity
Nov 18 '16 at 17:26
@odiggity you can check my answer, I finally made it working exactly as the BottomSheetBehavior, but from the top.
– Carlos Alberto Martínez Gadea
Nov 21 '18 at 11:17
@odiggity you can check my answer, I finally made it working exactly as the BottomSheetBehavior, but from the top.
– Carlos Alberto Martínez Gadea
Nov 21 '18 at 11:17
add a comment |
2 Answers
2
active
oldest
votes
Here is the basis of my solution that I commented about above.
I will come back and flesh it out later.
@Override
protected void onCreate(
@Nullable
Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (isFinishing())
{
return;
}
setContentView(R.layout.activity_home);
...
mGroupBottomSheetFiller = (ViewGroup) findViewById(R.id.groupBottomSheetFiller);
final NestedScrollView bottomSheetMap = (NestedScrollView) findViewById(R.id.bottomSheetMap);
mBottomSheetMapBehavior = BottomSheetBehavior.from(bottomSheetMap);
mBottomSheetMapBehavior.setBottomSheetCallback(new BottomSheetCallback()
{
@Override
public void onStateChanged(
@NonNull
View bottomSheet,
int newState)
{
//Log.e(TAG, "mBottomSheetMapBehavior.onStateChanged(bottomSheet, newState=" +
// bottomSheetBehaviorStateToString(newState) + ')');
int visibility = isBottomSheetExpanded(mBottomSheetMapBehavior) ? View.VISIBLE : View.GONE;
mImageBottomSheetMapClose.setVisibility(visibility);
}
@Override
public void onSlide(
@NonNull
View bottomSheet,
float slideOffset)
{
//Log.e(TAG, "mBottomSheetMapBehavior.onStateChanged(bottomSheet, slideOffset=" + slideOffset + ')');
resizeMap();
}
});
bottomSheetMap.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
@Override
public void onGlobalLayout()
{
//Log.e(TAG, "onGlobalLayout()");
bottomSheetMap.getViewTreeObserver().removeOnGlobalLayoutListener(this);
resizeMap();
}
});
...
}
private void resizeMap()
{
int screenHeightPixels = PbPlatformUtils.getScreenHeightPixels();
//Log.e(TAG, "resizeMap: screenHeightPixels=" + screenHeightPixels);
int location = new int[2];
mGroupMap.getLocationInWindow(location);
//Log.e(TAG, "resizeMap: getLocationInWindow=" + Arrays.toString(location));
LayoutParams groupMapLayoutParams = mGroupMap.getLayoutParams();
groupMapLayoutParams.height = screenHeightPixels - location[1];
mGroupMap.requestLayout();
}
public static String bottomSheetBehaviorStateToString(int state)
{
String s;
switch (state)
{
case BottomSheetBehavior.STATE_COLLAPSED:
s = "STATE_COLLAPSED";
break;
case BottomSheetBehavior.STATE_DRAGGING:
s = "STATE_DRAGGING";
break;
case BottomSheetBehavior.STATE_EXPANDED:
s = "STATE_EXPANDED";
break;
case BottomSheetBehavior.STATE_HIDDEN:
s = "STATE_HIDDEN";
break;
case BottomSheetBehavior.STATE_SETTLING:
s = "STATE_SETTLING";
break;
default:
s = "UNKNOWN";
break;
}
return s + '(' + state + ')';
}
private static boolean isBottomSheetExpanded(
@NonNull
BottomSheetBehavior bottomSheetBehavior)
{
return bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED;
}
private void bottomSheetMapExpand()
{
mGroupBottomSheetFiller.setVisibility(View.VISIBLE);
int peekHeightPx = getResources().getDimensionPixelSize(R.dimen.home_bottom_sheet_map_peek_height);
mBottomSheetMapBehavior.setPeekHeight(peekHeightPx);
mBottomSheetMapBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
mBottomSheetMapBehavior.setHideable(false);
}
private void bottomSheetMapCollapse()
{
mGroupBottomSheetFiller.setVisibility(View.VISIBLE);
int peekHeightPx = getResources().getDimensionPixelSize(R.dimen.home_bottom_sheet_map_peek_height);
mBottomSheetMapBehavior.setPeekHeight(peekHeightPx);
mBottomSheetMapBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
mBottomSheetMapBehavior.setHideable(false);
}
private void bottomSheetMapHide()
{
mBottomSheetMapBehavior.setHideable(true);
mBottomSheetMapBehavior.setPeekHeight(0);
mBottomSheetMapBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
mGroupBottomSheetFiller.setVisibility(View.GONE);
}
1
did you encounter compatibility issues with this solution? in case you have a working app in the playstore using this functionality it'd be great to check it out :)
– carlosavoy
May 29 '17 at 15:33
You can check my answer @swooby , perhaps it's nearer to what you were looking for. At least, it behaves exactly as I imagined a TopSheet to be equivalent to aBottomSheetBehavior
.
– Carlos Alberto Martínez Gadea
Nov 21 '18 at 11:18
Looks good @CarlosAlbertoMartínezGadea, but the implementation in my answer current fits my needs for an existing production app, so I haven't experimented with porting over to yours. If I do one day I'll mark yours as the preferred answer! Thanks!
– swooby
Nov 27 '18 at 21:07
add a comment |
This TopSheetBehavior
implementation ( https://github.com/MedveDomg/AndroidTopSheet/blob/master/library/src/main/java/com/github/techisfun/android/topsheet/TopSheetBehavior.java ) has proved to work pretty well in my case. I found many other TopSheetBehavior
that were incomplete or that crashed, but this one doesn't crash and works out of the box by only replacing the behavior parameter:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:behavior_hideable="true"
app:behavior_peekHeight="56dp"
app:layout_behavior="your.package.components.TopSheetBehavior">
<!-- Your content goes here -->
</LinearLayout>
That's the perfect way to do that. It's working smoothly and fine.
– Dheeraj Rijhwani
Nov 20 '18 at 18:05
Can I use this exact solution in closed source project? Or should I provide some references?
– Viktor Vostrikov
Dec 23 '18 at 15:08
@ViktorVostrikov yes, you can. It's under the Apache license. Here you have a few questions answered about the usage of code under the Apache license: resources.whitesourcesoftware.com/blog-whitesource/…
– Carlos Alberto Martínez Gadea
Dec 24 '18 at 11:01
@CarlosAlbertoMartínezGadea however it is stated that I need to still write somehow the owner of the library.. Don't know there should I provide credentials..
– Viktor Vostrikov
Dec 24 '18 at 11:17
@ViktorVostrikov to me, the phrase "If you redistribute software with any Apache licensed components, you must include a copy of the license, provide a clear Apache License attribution, and add modification notices to all the files that you modify." explains the situation quite clearly. You don't need to contact the author of the code but you must show that you are using the Apache License, with a link to that license.
– Carlos Alberto Martínez Gadea
Dec 24 '18 at 12:32
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f39088269%2fandroid-top-sheet-equivalent-of-bottom-sheet%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Here is the basis of my solution that I commented about above.
I will come back and flesh it out later.
@Override
protected void onCreate(
@Nullable
Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (isFinishing())
{
return;
}
setContentView(R.layout.activity_home);
...
mGroupBottomSheetFiller = (ViewGroup) findViewById(R.id.groupBottomSheetFiller);
final NestedScrollView bottomSheetMap = (NestedScrollView) findViewById(R.id.bottomSheetMap);
mBottomSheetMapBehavior = BottomSheetBehavior.from(bottomSheetMap);
mBottomSheetMapBehavior.setBottomSheetCallback(new BottomSheetCallback()
{
@Override
public void onStateChanged(
@NonNull
View bottomSheet,
int newState)
{
//Log.e(TAG, "mBottomSheetMapBehavior.onStateChanged(bottomSheet, newState=" +
// bottomSheetBehaviorStateToString(newState) + ')');
int visibility = isBottomSheetExpanded(mBottomSheetMapBehavior) ? View.VISIBLE : View.GONE;
mImageBottomSheetMapClose.setVisibility(visibility);
}
@Override
public void onSlide(
@NonNull
View bottomSheet,
float slideOffset)
{
//Log.e(TAG, "mBottomSheetMapBehavior.onStateChanged(bottomSheet, slideOffset=" + slideOffset + ')');
resizeMap();
}
});
bottomSheetMap.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
@Override
public void onGlobalLayout()
{
//Log.e(TAG, "onGlobalLayout()");
bottomSheetMap.getViewTreeObserver().removeOnGlobalLayoutListener(this);
resizeMap();
}
});
...
}
private void resizeMap()
{
int screenHeightPixels = PbPlatformUtils.getScreenHeightPixels();
//Log.e(TAG, "resizeMap: screenHeightPixels=" + screenHeightPixels);
int location = new int[2];
mGroupMap.getLocationInWindow(location);
//Log.e(TAG, "resizeMap: getLocationInWindow=" + Arrays.toString(location));
LayoutParams groupMapLayoutParams = mGroupMap.getLayoutParams();
groupMapLayoutParams.height = screenHeightPixels - location[1];
mGroupMap.requestLayout();
}
public static String bottomSheetBehaviorStateToString(int state)
{
String s;
switch (state)
{
case BottomSheetBehavior.STATE_COLLAPSED:
s = "STATE_COLLAPSED";
break;
case BottomSheetBehavior.STATE_DRAGGING:
s = "STATE_DRAGGING";
break;
case BottomSheetBehavior.STATE_EXPANDED:
s = "STATE_EXPANDED";
break;
case BottomSheetBehavior.STATE_HIDDEN:
s = "STATE_HIDDEN";
break;
case BottomSheetBehavior.STATE_SETTLING:
s = "STATE_SETTLING";
break;
default:
s = "UNKNOWN";
break;
}
return s + '(' + state + ')';
}
private static boolean isBottomSheetExpanded(
@NonNull
BottomSheetBehavior bottomSheetBehavior)
{
return bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED;
}
private void bottomSheetMapExpand()
{
mGroupBottomSheetFiller.setVisibility(View.VISIBLE);
int peekHeightPx = getResources().getDimensionPixelSize(R.dimen.home_bottom_sheet_map_peek_height);
mBottomSheetMapBehavior.setPeekHeight(peekHeightPx);
mBottomSheetMapBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
mBottomSheetMapBehavior.setHideable(false);
}
private void bottomSheetMapCollapse()
{
mGroupBottomSheetFiller.setVisibility(View.VISIBLE);
int peekHeightPx = getResources().getDimensionPixelSize(R.dimen.home_bottom_sheet_map_peek_height);
mBottomSheetMapBehavior.setPeekHeight(peekHeightPx);
mBottomSheetMapBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
mBottomSheetMapBehavior.setHideable(false);
}
private void bottomSheetMapHide()
{
mBottomSheetMapBehavior.setHideable(true);
mBottomSheetMapBehavior.setPeekHeight(0);
mBottomSheetMapBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
mGroupBottomSheetFiller.setVisibility(View.GONE);
}
1
did you encounter compatibility issues with this solution? in case you have a working app in the playstore using this functionality it'd be great to check it out :)
– carlosavoy
May 29 '17 at 15:33
You can check my answer @swooby , perhaps it's nearer to what you were looking for. At least, it behaves exactly as I imagined a TopSheet to be equivalent to aBottomSheetBehavior
.
– Carlos Alberto Martínez Gadea
Nov 21 '18 at 11:18
Looks good @CarlosAlbertoMartínezGadea, but the implementation in my answer current fits my needs for an existing production app, so I haven't experimented with porting over to yours. If I do one day I'll mark yours as the preferred answer! Thanks!
– swooby
Nov 27 '18 at 21:07
add a comment |
Here is the basis of my solution that I commented about above.
I will come back and flesh it out later.
@Override
protected void onCreate(
@Nullable
Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (isFinishing())
{
return;
}
setContentView(R.layout.activity_home);
...
mGroupBottomSheetFiller = (ViewGroup) findViewById(R.id.groupBottomSheetFiller);
final NestedScrollView bottomSheetMap = (NestedScrollView) findViewById(R.id.bottomSheetMap);
mBottomSheetMapBehavior = BottomSheetBehavior.from(bottomSheetMap);
mBottomSheetMapBehavior.setBottomSheetCallback(new BottomSheetCallback()
{
@Override
public void onStateChanged(
@NonNull
View bottomSheet,
int newState)
{
//Log.e(TAG, "mBottomSheetMapBehavior.onStateChanged(bottomSheet, newState=" +
// bottomSheetBehaviorStateToString(newState) + ')');
int visibility = isBottomSheetExpanded(mBottomSheetMapBehavior) ? View.VISIBLE : View.GONE;
mImageBottomSheetMapClose.setVisibility(visibility);
}
@Override
public void onSlide(
@NonNull
View bottomSheet,
float slideOffset)
{
//Log.e(TAG, "mBottomSheetMapBehavior.onStateChanged(bottomSheet, slideOffset=" + slideOffset + ')');
resizeMap();
}
});
bottomSheetMap.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
@Override
public void onGlobalLayout()
{
//Log.e(TAG, "onGlobalLayout()");
bottomSheetMap.getViewTreeObserver().removeOnGlobalLayoutListener(this);
resizeMap();
}
});
...
}
private void resizeMap()
{
int screenHeightPixels = PbPlatformUtils.getScreenHeightPixels();
//Log.e(TAG, "resizeMap: screenHeightPixels=" + screenHeightPixels);
int location = new int[2];
mGroupMap.getLocationInWindow(location);
//Log.e(TAG, "resizeMap: getLocationInWindow=" + Arrays.toString(location));
LayoutParams groupMapLayoutParams = mGroupMap.getLayoutParams();
groupMapLayoutParams.height = screenHeightPixels - location[1];
mGroupMap.requestLayout();
}
public static String bottomSheetBehaviorStateToString(int state)
{
String s;
switch (state)
{
case BottomSheetBehavior.STATE_COLLAPSED:
s = "STATE_COLLAPSED";
break;
case BottomSheetBehavior.STATE_DRAGGING:
s = "STATE_DRAGGING";
break;
case BottomSheetBehavior.STATE_EXPANDED:
s = "STATE_EXPANDED";
break;
case BottomSheetBehavior.STATE_HIDDEN:
s = "STATE_HIDDEN";
break;
case BottomSheetBehavior.STATE_SETTLING:
s = "STATE_SETTLING";
break;
default:
s = "UNKNOWN";
break;
}
return s + '(' + state + ')';
}
private static boolean isBottomSheetExpanded(
@NonNull
BottomSheetBehavior bottomSheetBehavior)
{
return bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED;
}
private void bottomSheetMapExpand()
{
mGroupBottomSheetFiller.setVisibility(View.VISIBLE);
int peekHeightPx = getResources().getDimensionPixelSize(R.dimen.home_bottom_sheet_map_peek_height);
mBottomSheetMapBehavior.setPeekHeight(peekHeightPx);
mBottomSheetMapBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
mBottomSheetMapBehavior.setHideable(false);
}
private void bottomSheetMapCollapse()
{
mGroupBottomSheetFiller.setVisibility(View.VISIBLE);
int peekHeightPx = getResources().getDimensionPixelSize(R.dimen.home_bottom_sheet_map_peek_height);
mBottomSheetMapBehavior.setPeekHeight(peekHeightPx);
mBottomSheetMapBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
mBottomSheetMapBehavior.setHideable(false);
}
private void bottomSheetMapHide()
{
mBottomSheetMapBehavior.setHideable(true);
mBottomSheetMapBehavior.setPeekHeight(0);
mBottomSheetMapBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
mGroupBottomSheetFiller.setVisibility(View.GONE);
}
1
did you encounter compatibility issues with this solution? in case you have a working app in the playstore using this functionality it'd be great to check it out :)
– carlosavoy
May 29 '17 at 15:33
You can check my answer @swooby , perhaps it's nearer to what you were looking for. At least, it behaves exactly as I imagined a TopSheet to be equivalent to aBottomSheetBehavior
.
– Carlos Alberto Martínez Gadea
Nov 21 '18 at 11:18
Looks good @CarlosAlbertoMartínezGadea, but the implementation in my answer current fits my needs for an existing production app, so I haven't experimented with porting over to yours. If I do one day I'll mark yours as the preferred answer! Thanks!
– swooby
Nov 27 '18 at 21:07
add a comment |
Here is the basis of my solution that I commented about above.
I will come back and flesh it out later.
@Override
protected void onCreate(
@Nullable
Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (isFinishing())
{
return;
}
setContentView(R.layout.activity_home);
...
mGroupBottomSheetFiller = (ViewGroup) findViewById(R.id.groupBottomSheetFiller);
final NestedScrollView bottomSheetMap = (NestedScrollView) findViewById(R.id.bottomSheetMap);
mBottomSheetMapBehavior = BottomSheetBehavior.from(bottomSheetMap);
mBottomSheetMapBehavior.setBottomSheetCallback(new BottomSheetCallback()
{
@Override
public void onStateChanged(
@NonNull
View bottomSheet,
int newState)
{
//Log.e(TAG, "mBottomSheetMapBehavior.onStateChanged(bottomSheet, newState=" +
// bottomSheetBehaviorStateToString(newState) + ')');
int visibility = isBottomSheetExpanded(mBottomSheetMapBehavior) ? View.VISIBLE : View.GONE;
mImageBottomSheetMapClose.setVisibility(visibility);
}
@Override
public void onSlide(
@NonNull
View bottomSheet,
float slideOffset)
{
//Log.e(TAG, "mBottomSheetMapBehavior.onStateChanged(bottomSheet, slideOffset=" + slideOffset + ')');
resizeMap();
}
});
bottomSheetMap.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
@Override
public void onGlobalLayout()
{
//Log.e(TAG, "onGlobalLayout()");
bottomSheetMap.getViewTreeObserver().removeOnGlobalLayoutListener(this);
resizeMap();
}
});
...
}
private void resizeMap()
{
int screenHeightPixels = PbPlatformUtils.getScreenHeightPixels();
//Log.e(TAG, "resizeMap: screenHeightPixels=" + screenHeightPixels);
int location = new int[2];
mGroupMap.getLocationInWindow(location);
//Log.e(TAG, "resizeMap: getLocationInWindow=" + Arrays.toString(location));
LayoutParams groupMapLayoutParams = mGroupMap.getLayoutParams();
groupMapLayoutParams.height = screenHeightPixels - location[1];
mGroupMap.requestLayout();
}
public static String bottomSheetBehaviorStateToString(int state)
{
String s;
switch (state)
{
case BottomSheetBehavior.STATE_COLLAPSED:
s = "STATE_COLLAPSED";
break;
case BottomSheetBehavior.STATE_DRAGGING:
s = "STATE_DRAGGING";
break;
case BottomSheetBehavior.STATE_EXPANDED:
s = "STATE_EXPANDED";
break;
case BottomSheetBehavior.STATE_HIDDEN:
s = "STATE_HIDDEN";
break;
case BottomSheetBehavior.STATE_SETTLING:
s = "STATE_SETTLING";
break;
default:
s = "UNKNOWN";
break;
}
return s + '(' + state + ')';
}
private static boolean isBottomSheetExpanded(
@NonNull
BottomSheetBehavior bottomSheetBehavior)
{
return bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED;
}
private void bottomSheetMapExpand()
{
mGroupBottomSheetFiller.setVisibility(View.VISIBLE);
int peekHeightPx = getResources().getDimensionPixelSize(R.dimen.home_bottom_sheet_map_peek_height);
mBottomSheetMapBehavior.setPeekHeight(peekHeightPx);
mBottomSheetMapBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
mBottomSheetMapBehavior.setHideable(false);
}
private void bottomSheetMapCollapse()
{
mGroupBottomSheetFiller.setVisibility(View.VISIBLE);
int peekHeightPx = getResources().getDimensionPixelSize(R.dimen.home_bottom_sheet_map_peek_height);
mBottomSheetMapBehavior.setPeekHeight(peekHeightPx);
mBottomSheetMapBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
mBottomSheetMapBehavior.setHideable(false);
}
private void bottomSheetMapHide()
{
mBottomSheetMapBehavior.setHideable(true);
mBottomSheetMapBehavior.setPeekHeight(0);
mBottomSheetMapBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
mGroupBottomSheetFiller.setVisibility(View.GONE);
}
Here is the basis of my solution that I commented about above.
I will come back and flesh it out later.
@Override
protected void onCreate(
@Nullable
Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (isFinishing())
{
return;
}
setContentView(R.layout.activity_home);
...
mGroupBottomSheetFiller = (ViewGroup) findViewById(R.id.groupBottomSheetFiller);
final NestedScrollView bottomSheetMap = (NestedScrollView) findViewById(R.id.bottomSheetMap);
mBottomSheetMapBehavior = BottomSheetBehavior.from(bottomSheetMap);
mBottomSheetMapBehavior.setBottomSheetCallback(new BottomSheetCallback()
{
@Override
public void onStateChanged(
@NonNull
View bottomSheet,
int newState)
{
//Log.e(TAG, "mBottomSheetMapBehavior.onStateChanged(bottomSheet, newState=" +
// bottomSheetBehaviorStateToString(newState) + ')');
int visibility = isBottomSheetExpanded(mBottomSheetMapBehavior) ? View.VISIBLE : View.GONE;
mImageBottomSheetMapClose.setVisibility(visibility);
}
@Override
public void onSlide(
@NonNull
View bottomSheet,
float slideOffset)
{
//Log.e(TAG, "mBottomSheetMapBehavior.onStateChanged(bottomSheet, slideOffset=" + slideOffset + ')');
resizeMap();
}
});
bottomSheetMap.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
@Override
public void onGlobalLayout()
{
//Log.e(TAG, "onGlobalLayout()");
bottomSheetMap.getViewTreeObserver().removeOnGlobalLayoutListener(this);
resizeMap();
}
});
...
}
private void resizeMap()
{
int screenHeightPixels = PbPlatformUtils.getScreenHeightPixels();
//Log.e(TAG, "resizeMap: screenHeightPixels=" + screenHeightPixels);
int location = new int[2];
mGroupMap.getLocationInWindow(location);
//Log.e(TAG, "resizeMap: getLocationInWindow=" + Arrays.toString(location));
LayoutParams groupMapLayoutParams = mGroupMap.getLayoutParams();
groupMapLayoutParams.height = screenHeightPixels - location[1];
mGroupMap.requestLayout();
}
public static String bottomSheetBehaviorStateToString(int state)
{
String s;
switch (state)
{
case BottomSheetBehavior.STATE_COLLAPSED:
s = "STATE_COLLAPSED";
break;
case BottomSheetBehavior.STATE_DRAGGING:
s = "STATE_DRAGGING";
break;
case BottomSheetBehavior.STATE_EXPANDED:
s = "STATE_EXPANDED";
break;
case BottomSheetBehavior.STATE_HIDDEN:
s = "STATE_HIDDEN";
break;
case BottomSheetBehavior.STATE_SETTLING:
s = "STATE_SETTLING";
break;
default:
s = "UNKNOWN";
break;
}
return s + '(' + state + ')';
}
private static boolean isBottomSheetExpanded(
@NonNull
BottomSheetBehavior bottomSheetBehavior)
{
return bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED;
}
private void bottomSheetMapExpand()
{
mGroupBottomSheetFiller.setVisibility(View.VISIBLE);
int peekHeightPx = getResources().getDimensionPixelSize(R.dimen.home_bottom_sheet_map_peek_height);
mBottomSheetMapBehavior.setPeekHeight(peekHeightPx);
mBottomSheetMapBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
mBottomSheetMapBehavior.setHideable(false);
}
private void bottomSheetMapCollapse()
{
mGroupBottomSheetFiller.setVisibility(View.VISIBLE);
int peekHeightPx = getResources().getDimensionPixelSize(R.dimen.home_bottom_sheet_map_peek_height);
mBottomSheetMapBehavior.setPeekHeight(peekHeightPx);
mBottomSheetMapBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
mBottomSheetMapBehavior.setHideable(false);
}
private void bottomSheetMapHide()
{
mBottomSheetMapBehavior.setHideable(true);
mBottomSheetMapBehavior.setPeekHeight(0);
mBottomSheetMapBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
mGroupBottomSheetFiller.setVisibility(View.GONE);
}
answered Nov 21 '16 at 20:18
swoobyswooby
1,7712431
1,7712431
1
did you encounter compatibility issues with this solution? in case you have a working app in the playstore using this functionality it'd be great to check it out :)
– carlosavoy
May 29 '17 at 15:33
You can check my answer @swooby , perhaps it's nearer to what you were looking for. At least, it behaves exactly as I imagined a TopSheet to be equivalent to aBottomSheetBehavior
.
– Carlos Alberto Martínez Gadea
Nov 21 '18 at 11:18
Looks good @CarlosAlbertoMartínezGadea, but the implementation in my answer current fits my needs for an existing production app, so I haven't experimented with porting over to yours. If I do one day I'll mark yours as the preferred answer! Thanks!
– swooby
Nov 27 '18 at 21:07
add a comment |
1
did you encounter compatibility issues with this solution? in case you have a working app in the playstore using this functionality it'd be great to check it out :)
– carlosavoy
May 29 '17 at 15:33
You can check my answer @swooby , perhaps it's nearer to what you were looking for. At least, it behaves exactly as I imagined a TopSheet to be equivalent to aBottomSheetBehavior
.
– Carlos Alberto Martínez Gadea
Nov 21 '18 at 11:18
Looks good @CarlosAlbertoMartínezGadea, but the implementation in my answer current fits my needs for an existing production app, so I haven't experimented with porting over to yours. If I do one day I'll mark yours as the preferred answer! Thanks!
– swooby
Nov 27 '18 at 21:07
1
1
did you encounter compatibility issues with this solution? in case you have a working app in the playstore using this functionality it'd be great to check it out :)
– carlosavoy
May 29 '17 at 15:33
did you encounter compatibility issues with this solution? in case you have a working app in the playstore using this functionality it'd be great to check it out :)
– carlosavoy
May 29 '17 at 15:33
You can check my answer @swooby , perhaps it's nearer to what you were looking for. At least, it behaves exactly as I imagined a TopSheet to be equivalent to a
BottomSheetBehavior
.– Carlos Alberto Martínez Gadea
Nov 21 '18 at 11:18
You can check my answer @swooby , perhaps it's nearer to what you were looking for. At least, it behaves exactly as I imagined a TopSheet to be equivalent to a
BottomSheetBehavior
.– Carlos Alberto Martínez Gadea
Nov 21 '18 at 11:18
Looks good @CarlosAlbertoMartínezGadea, but the implementation in my answer current fits my needs for an existing production app, so I haven't experimented with porting over to yours. If I do one day I'll mark yours as the preferred answer! Thanks!
– swooby
Nov 27 '18 at 21:07
Looks good @CarlosAlbertoMartínezGadea, but the implementation in my answer current fits my needs for an existing production app, so I haven't experimented with porting over to yours. If I do one day I'll mark yours as the preferred answer! Thanks!
– swooby
Nov 27 '18 at 21:07
add a comment |
This TopSheetBehavior
implementation ( https://github.com/MedveDomg/AndroidTopSheet/blob/master/library/src/main/java/com/github/techisfun/android/topsheet/TopSheetBehavior.java ) has proved to work pretty well in my case. I found many other TopSheetBehavior
that were incomplete or that crashed, but this one doesn't crash and works out of the box by only replacing the behavior parameter:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:behavior_hideable="true"
app:behavior_peekHeight="56dp"
app:layout_behavior="your.package.components.TopSheetBehavior">
<!-- Your content goes here -->
</LinearLayout>
That's the perfect way to do that. It's working smoothly and fine.
– Dheeraj Rijhwani
Nov 20 '18 at 18:05
Can I use this exact solution in closed source project? Or should I provide some references?
– Viktor Vostrikov
Dec 23 '18 at 15:08
@ViktorVostrikov yes, you can. It's under the Apache license. Here you have a few questions answered about the usage of code under the Apache license: resources.whitesourcesoftware.com/blog-whitesource/…
– Carlos Alberto Martínez Gadea
Dec 24 '18 at 11:01
@CarlosAlbertoMartínezGadea however it is stated that I need to still write somehow the owner of the library.. Don't know there should I provide credentials..
– Viktor Vostrikov
Dec 24 '18 at 11:17
@ViktorVostrikov to me, the phrase "If you redistribute software with any Apache licensed components, you must include a copy of the license, provide a clear Apache License attribution, and add modification notices to all the files that you modify." explains the situation quite clearly. You don't need to contact the author of the code but you must show that you are using the Apache License, with a link to that license.
– Carlos Alberto Martínez Gadea
Dec 24 '18 at 12:32
add a comment |
This TopSheetBehavior
implementation ( https://github.com/MedveDomg/AndroidTopSheet/blob/master/library/src/main/java/com/github/techisfun/android/topsheet/TopSheetBehavior.java ) has proved to work pretty well in my case. I found many other TopSheetBehavior
that were incomplete or that crashed, but this one doesn't crash and works out of the box by only replacing the behavior parameter:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:behavior_hideable="true"
app:behavior_peekHeight="56dp"
app:layout_behavior="your.package.components.TopSheetBehavior">
<!-- Your content goes here -->
</LinearLayout>
That's the perfect way to do that. It's working smoothly and fine.
– Dheeraj Rijhwani
Nov 20 '18 at 18:05
Can I use this exact solution in closed source project? Or should I provide some references?
– Viktor Vostrikov
Dec 23 '18 at 15:08
@ViktorVostrikov yes, you can. It's under the Apache license. Here you have a few questions answered about the usage of code under the Apache license: resources.whitesourcesoftware.com/blog-whitesource/…
– Carlos Alberto Martínez Gadea
Dec 24 '18 at 11:01
@CarlosAlbertoMartínezGadea however it is stated that I need to still write somehow the owner of the library.. Don't know there should I provide credentials..
– Viktor Vostrikov
Dec 24 '18 at 11:17
@ViktorVostrikov to me, the phrase "If you redistribute software with any Apache licensed components, you must include a copy of the license, provide a clear Apache License attribution, and add modification notices to all the files that you modify." explains the situation quite clearly. You don't need to contact the author of the code but you must show that you are using the Apache License, with a link to that license.
– Carlos Alberto Martínez Gadea
Dec 24 '18 at 12:32
add a comment |
This TopSheetBehavior
implementation ( https://github.com/MedveDomg/AndroidTopSheet/blob/master/library/src/main/java/com/github/techisfun/android/topsheet/TopSheetBehavior.java ) has proved to work pretty well in my case. I found many other TopSheetBehavior
that were incomplete or that crashed, but this one doesn't crash and works out of the box by only replacing the behavior parameter:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:behavior_hideable="true"
app:behavior_peekHeight="56dp"
app:layout_behavior="your.package.components.TopSheetBehavior">
<!-- Your content goes here -->
</LinearLayout>
This TopSheetBehavior
implementation ( https://github.com/MedveDomg/AndroidTopSheet/blob/master/library/src/main/java/com/github/techisfun/android/topsheet/TopSheetBehavior.java ) has proved to work pretty well in my case. I found many other TopSheetBehavior
that were incomplete or that crashed, but this one doesn't crash and works out of the box by only replacing the behavior parameter:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:behavior_hideable="true"
app:behavior_peekHeight="56dp"
app:layout_behavior="your.package.components.TopSheetBehavior">
<!-- Your content goes here -->
</LinearLayout>
edited Nov 21 '18 at 11:15
answered Aug 29 '18 at 17:41
Carlos Alberto Martínez GadeaCarlos Alberto Martínez Gadea
1,23411424
1,23411424
That's the perfect way to do that. It's working smoothly and fine.
– Dheeraj Rijhwani
Nov 20 '18 at 18:05
Can I use this exact solution in closed source project? Or should I provide some references?
– Viktor Vostrikov
Dec 23 '18 at 15:08
@ViktorVostrikov yes, you can. It's under the Apache license. Here you have a few questions answered about the usage of code under the Apache license: resources.whitesourcesoftware.com/blog-whitesource/…
– Carlos Alberto Martínez Gadea
Dec 24 '18 at 11:01
@CarlosAlbertoMartínezGadea however it is stated that I need to still write somehow the owner of the library.. Don't know there should I provide credentials..
– Viktor Vostrikov
Dec 24 '18 at 11:17
@ViktorVostrikov to me, the phrase "If you redistribute software with any Apache licensed components, you must include a copy of the license, provide a clear Apache License attribution, and add modification notices to all the files that you modify." explains the situation quite clearly. You don't need to contact the author of the code but you must show that you are using the Apache License, with a link to that license.
– Carlos Alberto Martínez Gadea
Dec 24 '18 at 12:32
add a comment |
That's the perfect way to do that. It's working smoothly and fine.
– Dheeraj Rijhwani
Nov 20 '18 at 18:05
Can I use this exact solution in closed source project? Or should I provide some references?
– Viktor Vostrikov
Dec 23 '18 at 15:08
@ViktorVostrikov yes, you can. It's under the Apache license. Here you have a few questions answered about the usage of code under the Apache license: resources.whitesourcesoftware.com/blog-whitesource/…
– Carlos Alberto Martínez Gadea
Dec 24 '18 at 11:01
@CarlosAlbertoMartínezGadea however it is stated that I need to still write somehow the owner of the library.. Don't know there should I provide credentials..
– Viktor Vostrikov
Dec 24 '18 at 11:17
@ViktorVostrikov to me, the phrase "If you redistribute software with any Apache licensed components, you must include a copy of the license, provide a clear Apache License attribution, and add modification notices to all the files that you modify." explains the situation quite clearly. You don't need to contact the author of the code but you must show that you are using the Apache License, with a link to that license.
– Carlos Alberto Martínez Gadea
Dec 24 '18 at 12:32
That's the perfect way to do that. It's working smoothly and fine.
– Dheeraj Rijhwani
Nov 20 '18 at 18:05
That's the perfect way to do that. It's working smoothly and fine.
– Dheeraj Rijhwani
Nov 20 '18 at 18:05
Can I use this exact solution in closed source project? Or should I provide some references?
– Viktor Vostrikov
Dec 23 '18 at 15:08
Can I use this exact solution in closed source project? Or should I provide some references?
– Viktor Vostrikov
Dec 23 '18 at 15:08
@ViktorVostrikov yes, you can. It's under the Apache license. Here you have a few questions answered about the usage of code under the Apache license: resources.whitesourcesoftware.com/blog-whitesource/…
– Carlos Alberto Martínez Gadea
Dec 24 '18 at 11:01
@ViktorVostrikov yes, you can. It's under the Apache license. Here you have a few questions answered about the usage of code under the Apache license: resources.whitesourcesoftware.com/blog-whitesource/…
– Carlos Alberto Martínez Gadea
Dec 24 '18 at 11:01
@CarlosAlbertoMartínezGadea however it is stated that I need to still write somehow the owner of the library.. Don't know there should I provide credentials..
– Viktor Vostrikov
Dec 24 '18 at 11:17
@CarlosAlbertoMartínezGadea however it is stated that I need to still write somehow the owner of the library.. Don't know there should I provide credentials..
– Viktor Vostrikov
Dec 24 '18 at 11:17
@ViktorVostrikov to me, the phrase "If you redistribute software with any Apache licensed components, you must include a copy of the license, provide a clear Apache License attribution, and add modification notices to all the files that you modify." explains the situation quite clearly. You don't need to contact the author of the code but you must show that you are using the Apache License, with a link to that license.
– Carlos Alberto Martínez Gadea
Dec 24 '18 at 12:32
@ViktorVostrikov to me, the phrase "If you redistribute software with any Apache licensed components, you must include a copy of the license, provide a clear Apache License attribution, and add modification notices to all the files that you modify." explains the situation quite clearly. You don't need to contact the author of the code but you must show that you are using the Apache License, with a link to that license.
– Carlos Alberto Martínez Gadea
Dec 24 '18 at 12:32
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f39088269%2fandroid-top-sheet-equivalent-of-bottom-sheet%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
3
I think you are going to sign up to do a substantial amount of heavy lifting to do two things. First, to create your custom implementation. Second, to identify how your implementation conflicts with the android implementation and to defend against those scenarios. My personal opinion, the Material Design Language has been put in place to visually communicate the ways your users can expect to interact with the app. Something like this may be great as a personal endeavour for learning, but once you hit the market - you need to expect that every single person won't understand how to use your app.
– apelsoczi
Aug 22 '16 at 20:44
I ended up just adding a bottomsheet layout that has a Toolbar at its top that allows the user to drag the toolbar up. The trick is then to resize the Map as the user drags the toolbar. I can post my code if anyone is interested.
– swooby
Sep 9 '16 at 21:08
I'd like to see it @swooby, I'm trying to do something similar
– odiggity
Nov 18 '16 at 17:26
@odiggity you can check my answer, I finally made it working exactly as the BottomSheetBehavior, but from the top.
– Carlos Alberto Martínez Gadea
Nov 21 '18 at 11:17