Author: Adam Evyčędo <git@apiote.xyz>
add landscape layout to journey searching
%!v(PANIC=String method: strings: negative Repeat count)
diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/journey/JourneyFragment.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/journey/JourneyFragment.kt index d70dc1c6f78dde7051b5797e069dd7b5dc29c6e0..2f9db1a9daa4e9aa6d4126759e6a47710a0d0450 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/journey/JourneyFragment.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/journey/JourneyFragment.kt @@ -6,6 +6,7 @@ package xyz.apiote.bimba.czwek.dashboard.ui.journey import android.annotation.SuppressLint import android.content.Context +import android.content.res.Configuration import android.graphics.RectF import android.graphics.drawable.LayerDrawable import android.location.Location @@ -89,8 +90,6 @@ savedInstanceState: Bundle? ): View { viewModel = ViewModelProvider(this)[JourneyViewModel::class.java] - // TODO separate layout: two columns for horizontal - _binding = FragmentJourneyBinding.inflate(inflater, container, false) val root: View = binding.root @@ -102,8 +101,16 @@ dashboard.viewModel.suggestions[DashboardViewModel.ORIGIN_KEY] = binding.originSuggestions dashboard.viewModel.suggestions[DashboardViewModel.DEST_KEY] = binding.destinationSuggestions + // TODO test upside down ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, windowInsets -> val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) + + binding.chipsParamsTime.updateLayoutParams<ViewGroup.MarginLayoutParams> { + if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) { + topMargin = insets.top + dpToPixelI(16f) + } + } + binding.originInput.updatePadding(left = insets.left, right = insets.right) binding.originInput.updateLayoutParams<ViewGroup.MarginLayoutParams> { topMargin = insets.top + dpToPixelI(16f) diff --git a/app/src/main/res/layout-land/fragment_journey.xml b/app/src/main/res/layout-land/fragment_journey.xml new file mode 100644 index 0000000000000000000000000000000000000000..6d61f4ad266345f85b9bd2dc53b958c0531b3902 --- /dev/null +++ b/app/src/main/res/layout-land/fragment_journey.xml @@ -0,0 +1,369 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- +SPDX-FileCopyrightText: Adam Evyčędo + +SPDX-License-Identifier: GPL-3.0-or-later +--> + +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tool="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tool:context="xyz.apiote.bimba.czwek.dashboard.ui.journey.JourneyFragment"> + + <androidx.constraintlayout.widget.Guideline + android:id="@+id/middle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical" + app:layout_constraintGuide_percent=".5" /> + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/origin_input" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginLeft="16dp" + android:layout_marginTop="16dp" + android:layout_marginRight="16dp" + android:hint="@string/origin_input_hint" + app:layout_constraintEnd_toEndOf="@+id/middle" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:startIconDrawable="@drawable/origin"> + + <com.google.android.material.textfield.TextInputEditText + android:id="@+id/origin" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:imeOptions="actionSearch" + android:inputType="text" /> + </com.google.android.material.textfield.TextInputLayout> + + <com.google.android.material.chip.ChipGroup + android:id="@+id/origin_suggestions" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="16dp" + android:layout_marginTop="4dp" + android:layout_marginRight="16dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/origin_input" /> + + <!-- via + required: false + List of via stops to visit (only stop IDs, no coordinates allowed for now). + maxItems: 2 + + viaMinimumStay + required: false + Optional. If not set, the default is `0,0` - no stay required. + For each `via` stop a minimum stay duration in minutes. + + The value `0` signals that it's allowed to stay in the same trip. + This enables via stays without counting a transfer and can lead + to better connections with less transfers. Transfer connections can + still be found with `viaMinimumStay=0`. + default: [ 0, 0 ] + type: array + maxItems: 2 + --> + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/destination_input" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginLeft="16dp" + android:layout_marginTop="16dp" + android:layout_marginRight="16dp" + android:hint="@string/destination_input_hint" + app:layout_constraintEnd_toEndOf="@id/middle" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/origin_suggestions" + app:startIconDrawable="@drawable/destination"> + + <com.google.android.material.textfield.TextInputEditText + android:id="@+id/destination" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:imeOptions="actionSearch" + android:inputType="text" /> + </com.google.android.material.textfield.TextInputLayout> + + <com.google.android.material.chip.ChipGroup + android:id="@+id/destination_suggestions" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="16dp" + android:layout_marginTop="4dp" + android:layout_marginRight="16dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/destination_input" /> + + + <com.google.android.material.chip.ChipGroup + android:id="@+id/chips_params_time" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginTop="16dp" + android:paddingStart="16dp" + android:paddingEnd="16dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="@id/middle" + app:layout_constraintTop_toTopOf="parent"> + + <com.google.android.material.chip.Chip + android:id="@+id/chip_time_reference" + style="@style/Widget.Material3.Chip.Filter" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:checkable="false" + android:text="@string/depart_after" + app:checkedIconEnabled="false" + app:closeIcon="@drawable/dropdown" + app:closeIconEnabled="true" + tool:ignore="MissingConstraints" /> + + <com.google.android.material.chip.Chip + android:id="@+id/chip_date" + style="@style/Widget.Material3.Chip.Filter" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:checkable="false" + android:text="@string/today" + app:checkedIconEnabled="false" + app:closeIcon="@drawable/dropdown" + app:closeIconEnabled="true" + tool:ignore="MissingConstraints" /> + + <com.google.android.material.chip.Chip + android:id="@+id/chip_time" + style="@style/Widget.Material3.Chip.Filter" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:checkable="false" + android:text="@string/now" + app:checkedIconEnabled="false" + app:closeIcon="@drawable/dropdown" + app:closeIconEnabled="true" + tool:ignore="MissingConstraints" /> + + </com.google.android.material.chip.ChipGroup> + + <com.google.android.material.chip.ChipGroup + android:id="@+id/chips_params_accessible" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:paddingStart="16dp" + android:paddingEnd="16dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="@id/middle" + app:layout_constraintTop_toBottomOf="@id/chips_params_time"> + + <com.google.android.material.chip.Chip + android:id="@+id/chip_wheelchair" + style="@style/Widget.Material3.Chip.Filter" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/wheelchair_accessible" + app:chipIcon="@drawable/wheelchair" + app:chipIconEnabled="true" + tool:ignore="MissingConstraints" /> + + <com.google.android.material.chip.Chip + android:id="@+id/chip_bike" + style="@style/Widget.Material3.Chip.Filter" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/bike_transport" + app:chipIcon="@drawable/bike" + app:chipIconEnabled="true" + tool:ignore="MissingConstraints" /> + + <!--<com.google.android.material.chip.Chip + android:id="@+id/chip_options" + style="@style/Widget.Material3.Chip.Filter" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/other_options" + app:chipIcon="@drawable/options" + app:chipIconEnabled="true" + tool:ignore="MissingConstraints" />--> + + </com.google.android.material.chip.ChipGroup> + + <Button + android:id="@+id/goButton" + style="@style/Widget.Material3.Button.Icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="16dp" + android:text="@string/go" + app:icon="@drawable/journey_outline" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="@id/middle" /> + + <!-- + - name: maxTransfers + required: false + The maximum number of allowed transfers. + If not provided, the routing uses the server-side default value + which is hardcoded and very high to cover all use cases. + schema: + type: integer + + - name: maxHours + required: false + The maximum travel time in hours. + If not provided, the routing to uses the value + hardcoded in the server which is usually quite high. + schema: + type: number + + - name: minTransferTime + required: false + Minimum transfer time for each transfer in minutes. + schema: + type: integer + default: 0 + + - name: additionalTransferTime + required: false + Additional transfer time reserved for each transfer in minutes. + schema: + type: integer + default: 0 + + - name: transferTimeFactor + required: false + Factor to multiply minimum required transfer times with. + Values smaller than 1.0 are not supported. + schema: + type: number + default: 1.0 + + - name: maxMatchingDistance + required: true + Maximum matching distance in meters to match geo coordinates to the street network. + schema: + type: number + default: 25 + + - name: transitModes + required: false + Optional. Default is `TRANSIT` which allows all transit modes (no restriction). + Allowed modes for the transit part. If empty, no transit connections will be computed. + For example, this can be used to allow only `METRO,SUBWAY,TRAM`. + schema: + default: + - TRANSIT + type: array + + - name: directModes + required: false + Optional. Default is `WALK` which will compute walking routes as direct connections. + Modes used for direction connections from start to destination without using transit. + Results will be returned on the `direct` key. + Note: Direct connections will only be returned on the first call. For paging calls, they can be omitted. + Note: Transit connections that are slower than the fastest direct connection will not show up. + This is being used as a cut-off during transit routing to speed up the search. + To prevent this, it's possible to send two separate requests (one with only `transitModes` and one with only `directModes`). + Only non-transit modes such as `WALK`, `BIKE`, `CAR`, `BIKE_SHARING`, etc. can be used. + schema: + default: + - WALK + type: array + + - name: preTransitModes + required: false + Optional. Default is `WALK`. Only applies if the `from` place is a coordinate (not a transit stop). Does not apply to direct connections (see `directModes`). + A list of modes that are allowed to be used from the `from` coordinate to the first transit stop. Example: `WALK,BIKE_SHARING`. + schema: + default: + - WALK + type: array + + - name: postTransitModes + required: false + Optional. Default is `WALK`. Only applies if the `to` place is a coordinate (not a transit stop). Does not apply to direct connections (see `directModes`). + A list of modes that are allowed to be used from the last transit stop to the `to` coordinate. Example: `WALK,BIKE_SHARING`. + schema: + default: + - WALK + type: array + + - name: numItineraries + required: false + The minimum number of itineraries to compute. + This is only relevant if `timetableView=true`. + schema: + type: integer + default: 5 + + - name: pageCursor + required: false + Use the cursor to go to the next "page" of itineraries. + Copy the cursor from the last response and keep the original request as is. + This will enable you to search for itineraries in the next or previous time-window. + + - name: timetableView + required: false + Search for the best trip options within a time window. + If true two itineraries are considered optimal + if one is better on arrival time (earliest wins) + and the other is better on departure time (latest wins). + In combination with arriveBy this parameter cover the following use cases: + `timetable=false` = waiting for the first transit departure/arrival is considered travel time: + - `arriveBy=true`: event (e.g. a meeting) starts at 10:00 am, + compute the best journeys that arrive by that time (maximizes departure time) + - `arriveBy=false`: event (e.g. a meeting) ends at 11:00 am, + compute the best journeys that depart after that time + `timetable=true` = optimize "later departure" + "earlier arrival" and give all options over a time window: + - `arriveBy=true`: the time window around `date` and `time` refers to the arrival time window + - `arriveBy=false`: the time window around `date` and `time` refers to the departure time window + schema: + type: boolean + default: true + + - name: searchWindow + required: false + Optional. Default is 2 hours which is `7200`. + The length of the search-window in seconds. Default value two hours. + - `arriveBy=true`: number of seconds between the earliest departure time and latest departure time + - `arriveBy=false`: number of seconds between the earliest arrival time and the latest arrival time + schema: + type: integer + default: 7200 + minium: 0 + + - name: maxPreTransitTime + required: false + Maximum time in seconds for the first street leg. + schema: + type: integer + default: 900 + minimum: 0 + + - name: maxPostTransitTime + required: false + Maximum time in seconds for the last street leg. + schema: + type: integer + default: 900 + minimum: 0 + + - name: maxDirectTime + required: false + Maximum time in seconds for direct connections. + schema: + type: integer + default: 1800 + minimum: 0 + --> + +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file