I use a Mapbox map in a scrollview. In this scrollview I have the main LinearLayout and inside this, I have 5 areas with different information. The Map is in the third area.
Due to the amount of data in the first and second area, while displaying, the Map area must not be visible and to see it, you'll need to scroll.
Unfortunatly, the Mapbox seems to have an "automatic center" sistem: as soon as the Scrollview start to be displayed, it's position is set automaticly to the center of the Map.
So the user has to scroll back to the top of the scrollview.
How to avoid this "initial position feature"?
Note: this is NOT a duplicate question from this: Using mapbox in scrollview, scrollview sliding to the position where mapbox is put in the page
as the problem is NOT "how to move the map and don't move the scrollview". The problem is the initial position of the scrollview. Also the answer "do mScrollView.scrollTo(0,0);" is NOT acceptable as with that, the scrollview is first centered to the map and AFTER, there is a scroll.
Edit: here are two pictures and more details.
This first snap show the scrollview in vertical mode. I've a first area named "INFORMAÇOES" a second one named "TIPO DE OCORENÇA", a third with the map and after than I have 2 others area.
Due to the size of area 1 and 2, in vertical mode, the map area is partially visible. This snap show the screen at start of display.
This second snap is taken at the same time so at start of display, but in horizontal mode. Of course, the amount of visible data is different. What we can see is that the map area seem to force a scroll in order to be displayed.
After making some test I discovered strange thinks: when you scroll, you commonly set the top of data at top of screen. In the case of the map it's not the case. The first element which appear quickly at start of the display is the Mapbox logo.
Here is the XML part:
<LinearLayout
android:layout_margin="5dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
android:layout_below="#id/linearLayout_type"
android:id="#+id/linearLayout_map">
<com.mapbox.mapboxsdk.maps.MapView
mapbox:zoom="12"
android:id="#+id/mapview_inter"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
The tests I've made:
1 - put a android:visibility="gone" in com.mapbox.mapboxsdk.maps.MapView. it's not allowed.
2 - put a android:visibility="invisible" in com.mapbox.mapboxsdk.maps.MapView. it's not allowed.
3 - put a android:visibility="invisible" in the linearlayout of the map (linearLayout). Change nothing. The map is not visible but the "scroll" happened.
4 - put a android:visibility="gone" in the linearlayout of the map (linearLayout). In that case, that's OK: the "INFORMAÇOES"part of the data is at top. But their is no rendering of the map. So when I perform a
LinearLayout tmp = (LinearLayout) findViewById(R.id.linearLayout_map);
tmp.setVisibility(View.VISIBLE);
to see the map, I see... nothing :(
Any suggestions?
First, you should give a either your LinearLayout a specific dp size or the MapView. Right now you are using match_parent for both. You can force the ScrollView to the top by using scrollView.fullScroll(ScrollView.FOCUS_UP); inside the OnMapReady callback which fixed the issue for me.
Related
i have this problem in my android mobile app, i am using kotlin.
In the main of the project I have a list of cards, made through RecyclerView, when the cards are of a greater number than the screen can accommodate, the vertical scrolling is rightly enabled. As soon as I scroll the list vertically, the action is completed, but upon release I can no longer click anywhere within my app. (clicks work outside the app)
This is the HTML of that piece of code:
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="#+id/itemsswipetorefreshSite"
android:layout_width="wrap_content"
android:layout_height="0px"
android:layout_weight="1">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerViewSite"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="#dimen/twenty">
</androidx.recyclerview.widget.RecyclerView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
This piece of code is contained in a CoordinatorLayout inside which there is a ConstraintLayout which in turn has a LinearLayout that encloses the list.
The same problem does not occur in other parts of the app, or in other components / fragments I have other lists, made in the exact same way, but under this situation they do not produce this bug.
The log that is produced at the time of the bug (from the beginning of the scrolling) is the following:
I/HwViewRootImpl: removeInvalidNode all the node in jank list is out of time
W/HiTouch_PressGestureDetector: Touch pointer move a lot. The moving distance of X is:7.0, limit is:60The moving distance of Y is:61.94568, limit is:60
D/OverScrollerOptimization: fling time is flingTime = 1.9100340578075632 velocity = 1261
D/OverScrollerOptimization: fling time is flingTime = 1.9100340578075632 velocity = 1261
but the same is produced, very similar in the other lists for the same action.
Your every help is truly precious, thank you!
set layout_height to wrap_content in both swipeRefreshlayout and also in your recyclerView
[SOLVED]
Maybe it can help someone who is in the same situation as me: I found that in the adapter file of the list in question I found a
requireActivity (). window.setFlags (WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
that it didn't have to be there and every time I touched the list it was activated. Typical problem of a hasty copy and paste.
It works just fine when I run the app, but when working in studio the height of the recycler view is as tall as 1.5-2 screens which really slows down the work flow because I need to either scroll a lot or set it to match constraint and just change it back to wrap content before everytime I run the app. Has anyone experienced this before? First time for me.
This is my recycler, can't see anything here that should make this happen:
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/itinerary_sample_photos_recycler"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
app:layout_constraintTop_toBottomOf="#+id/itinerary_youtube_player_card"
app:layout_constraintEnd_toEndOf="#+id/itinerary_youtube_player_card"
app:layout_constraintStart_toStartOf="#+id/itinerary_youtube_player_card"/>
And this is how it looks. Notice, the area at the bottom where it says "buy 6.99" is a floating container fixed at the bottom of the screen. The recycler view stretches inside the scroll layout. It is selected so you can see the outline.
When you are using Constraint layout then it is worth using MATCH_CONSTRAINT that means 0dp for both width and height.
android:layout_width="0dp"
android:layout_height="0dp"
In my app I am calling API to get list of people with some informations (address, phone numbers etc.). Under every phone number, I am creating programatically 3 buttons (add to contacts, edit and call). Problem is, that last button is cut off (small screen). I am using Linear Layout horizontal.
Is there any way to control size of screen and if needed, put last button to second line? When I rotate screen to landscape, I have enough space, so buttons should stay in one line.
Now, I am using horizontalScrollView with visible scrollbar. It's working, but I am not very satisfied with it.
Thanks for help.
I'm not really sure if you can do that with LinearLayout. But you could do that using FlowLayout. Check this link: https://github.com/ultimate-deej/FlowLayout-for-Android.
This layout moves the buttons to the next line if there is no space for them on the screen.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weight="1" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weight="1" />
</LinearLayout>
the weight attribute will automatically adjust your button size
make sure you set width to match parent for all buttons.
Best to create a new variant of the listitem layout for smaller screenshots:
layout-w200dp/listitem.xml : layout with 3 buttons on one line
layout/listitem.xml : layout with buttons on separate lines
Android will then choose the multiline layout when the current available width is smaller than 200dp. (Note that you can still tweak the 200 to a different value)
Alternatively you can also use an alternatieve linearlayout which does the wrapping for you: Flowlayout
This is probably more complicated to achieve that you wan't it to be but the best shot is to use some adapter based solution:
GridView - this is the old solution, better go for the 2nd
RecyclerView with StaggeredLayoutManager setup to your needs
Simple solution is using android:layout_weight="1" and android:layout_width="0dp" as params for each button in your LinearLayout but then they will fit the whole screen and take the same percent of the width, and if the screen is too small buttons might get cut off.
So imagine a view with 9 tiles that looks something like this:
(tile1) (tile2) (tile3)
(tile4) (tile5) (tile6)
(tile7) (tile8) (tile9)
One tile takes up most of the screen. I have this set up already with a horizontalscrollgroup nested inside a scrollgroup to enable both horizontal and vertical scrolling but the problem is that the view starts off with tile1 in the center of the screen. I want the view to start off with tile 5 in the center and give the user the ability to scroll up, down, left, right, and diagonally. How can I implement this?
I guess my main issue is centering the view on tile5. Also is this is a good way to implement both horizontal and vertical scrolling or is there a more proper way of doing this?
Sorry I'm a beginner with mobile ui programming.
Try this :
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="match_parent">
</HorizontalScrollView>
</ScrollView>
As I am actually not very confident with programatically changing Views, I have following problem:
At the first start of my app, I want to have an overlay for the main screen, that tells the user to have a look at the settings, as there are two critical options the user has to configure.
I don't want to use an AlertDialog and rather not use a wizard. So, I decided to take an approach similar to Go SMS and create an overlay at the first start. The mockup I created looks like this:
Normal menu:
First start:
So these are the problems I have:
Like I said, I don't want to use a screenshot overlaying on first start, as this would take too much space and would not be language and screen independent.
I would have the circle as an png, but I don't know how exactly put it over the image
The same problem with the text
And finally I want to put a semi-transparent white over the app. It does not necessarily need the hole for the icon, though it would be nice.
In case you need the Layout Source, you can get it at pastebin
So, I just need to get a start here, if it is better to use LayoutInflater or ViewStub and how to realize it, as I have absolutely no experience with it...
Thanks!
/edit: I uploaded a new, more well-arranged layout.
I have faced a similar problem, I client wanted a walkthrough of the application, where the entire screen had to become whiter (as they said: "transparent"), except for the button being explained by an overlay speech-bubble.
Fortunately for you, your layout is not nearly as complicated as the one I had to work with :)
Now, you can get the transparency-effect in two ways, either have a white background and call all the views setAlpha() methods, or you can create a half-transparent white overlay.
If you go with the overlay, you'll have to find a way to display the opaque buttons through the overlay. This can get a bit complicated.
If you go with the first option, you can just setAlpha(1) on the opaque view to get it to show up.
The setAlpha() method is only available from api version 11+, so if you target an earlier version, you might have to do it in a slightly more complicated way.
Example of setting alpha on views pre-honeycomb:
Layout for your buttons (make them however you want, just make them similar so you can loop through them):
<LinearLayout
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:tag="image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/tile"/>
<TextView
android:tag="text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FF000000"
android:text="button1"/>
</LinearLayout>
In your program, when you are want to make the buttons transparent:
LinearLayout l = (LinearLayout) findViewById(R.id.button1);
((ImageView)l.findViewWithTag("image")).setAlpha(0x7F);
((TextView)l.findViewWithTag("text")).setTextColor(0x7F000000);
When you have decided on how you want to create the transparency effect, you will have to decide on how to display the overlay-text/bubble. You'll most likely want to put this in a separate layer on top of your entire layout, to make sure that it is not affected by your new view.
One way to achieve this is by changing your root layout element to a FrameLayout, and then creating/displaying in this. e.g:
<FrameLayout background="#FFFF"> <!-- white background, just in case -->
<LinearLayout>
<!-- the rest of your layout -->
</LinearLayout>
<LinearLayout visibility="gone"> <!-- this will be your overlay view -->
<ImageView /> <!-- the arrow/ring -->
<TextView /> <!-- the description -->
</LinearLayout>
</FrameLayout>
When the introduction is displayed, you set the position of the hidden overlay-view to the position of the table item to be explained, change the text to an appropriate string/resource and display the view.
When the introduction is over, you reset the alpha values of all buttons, and set the visibility of the overlay to gone again.
Since I don't have much experience with ViewStub, I would do it with LayoutInflater.
First of all, you need to have a second layout loaded on top of your current layout. The easiest is to have a FrameLayout, which has as one child your current view, and the dynamically you load the second child on the first start. When you load a content view in an Activity, it will be attached to some already created views (some DecorView, a FrameLayout, etc). So you can either re-use the existing FrameLayout, or you can create a new one.
I would vote for the second solution, since it's more stable (I just mentioned the other possibility in case you want to minimize the number of layers).
So, as a first step, wrap your current layout inside a FrameLayout, and give it an id, let's say "#id/root".
Then, in the onCreate method, you can have something like this:
setContentView(R.layout.main);
if (isFirstRun()) {
ViewGroup parent = (ViewGroup)findViewById(R.id.root); // locate the FrameLayout
LayoutInflater li = LayoutInflater.from(this); // get an instance of LayoutInflater
li.inflate(R.layout.overlay, parent);
}
So far you will have the overlay loaded. Now it's up to you to define the overlay.
To make the whitening effect, just set the following attribute on the root view in your overlay.xml layout:
android:background="#40ffffff"
To position the circle, first you need to find it's location. You can use the View.getLocationOnScreen to get the absolute coordinate of the icon (below the circle) on the screen. Then you can have two options:
either create a custom view (for the overlay) and manually draw the circle at the given location
or add the circle using an ImageView and adjust the left and top margins based on the coordinates