### Activity Setup for Predictive Back Custom Animations Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/predictiveback/README.md This code initializes the activity and replaces the initial fragment. Use setEnterTransition, setExitTransition, etc., where possible. ```kotlin // PBSetCustomAnimationsActivity.kt override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) "..." supportFragmentManager.commit { replace(R.id.fragment_container, PBSetCustomAnimationsFirstFragment()) } } ``` -------------------------------- ### Clone Connectivity Samples Repository Source: https://github.com/android/platform-samples/blob/main/samples/connectivity/UwbRanging/README.md Use this Git command to clone the repository containing the Android UWB sample project. Ensure you have Git installed. ```bash git clone git@github.com:android/connectivity-samples.git ``` -------------------------------- ### MotionLayout with CoordinatorLayout Integration (1) Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/constraintlayout/README.md Shows how MotionLayout can be integrated with CoordinatorLayout for complex scrolling and animation effects. This example focuses on a specific interaction pattern. ```xml ``` ```xml ``` -------------------------------- ### Shared Element Fragment Transition Setup Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/predictiveback/README.md Initiates a shared element transition between fragments. Ensure fragment and transition dependencies are updated for predictive back gesture compatibility. ```kotlin binding.sharedElementCrossFragment.setOnClickListener { findNavController().navigate( R.id.show_PBSharedElementTransitionFragment, null, null, FragmentNavigatorExtras(it to "second_card") ) } ``` -------------------------------- ### MotionLayout with ImageFilterView Animation (Variant) Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/constraintlayout/README.md Another example of animating an ImageFilterView with MotionLayout, showcasing different filter properties or keyframe configurations. ```xml ``` ```xml ``` -------------------------------- ### Audio Loop Source Utility Source: https://github.com/android/platform-samples/blob/main/samples/connectivity/audio/README.md A simple utility class demonstrating how to loop audio from an input source to an output source using AudioTrack and AudioRecord. Ensure proper audio buffer handling and thread management for real-time performance. ```kotlin package com.example.platform.connectivity.audio import android.media.AudioFormat import android.media.AudioRecord import android.media.AudioTrack import android.media.MediaRecorder import java.util.concurrent.atomic.AtomicBoolean class AudioLoopSource { private var audioRecord: AudioRecord? = null private var audioTrack: AudioTrack? = null private val isLooping = AtomicBoolean(false) fun startLooping(bufferSize: Int) { if (isLooping.compareAndSet(false, true)) { try { // Initialize AudioRecord audioRecord = AudioRecord( MediaRecorder.AudioSource.MIC, SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT, bufferSize ) // Initialize AudioTrack audioTrack = AudioTrack( AudioManager.STREAM_MUSIC, SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT, bufferSize, AudioTrack.MODE_STREAM ) audioRecord?.startRecording() audioTrack?.play() // Start the loop thread Thread(audioLoopRunnable).start() } catch (e: Exception) { stopLooping() e.printStackTrace() } } } fun stopLooping() { if (isLooping.compareAndSet(true, false)) { audioRecord?.stop() audioTrack?.stop() audioRecord?.release() audioTrack?.release() audioRecord = null audioTrack = null } } private val audioLoopRunnable = Runnable { val buffer = ShortArray(BUFFER_SIZE) while (isLooping.get()) { val readResult = audioRecord?.read(buffer, 0, BUFFER_SIZE) ?: 0 if (readResult > 0) { audioTrack?.write(buffer, 0, readResult) ?: 0 } } } companion object { private const val SAMPLE_RATE = 44100 private const val CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_MONO or AudioFormat.CHANNEL_OUT_MONO private const val AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT private const val BUFFER_SIZE = 1024 // Example buffer size } } ``` -------------------------------- ### Basic Drag and Drop with Views Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/draganddrop/README.md Demonstrates basic drag-and-drop implementation using `onLongClickListener` and implementing the `DragListener` callback in Android Views. ```kotlin package com.example.platform.ui.draganddrop import android.content.ClipData import android.content.ClipDescription.MIMETYPE_TEXT_PLAIN import android.os.Build import android.os.Bundle import android.view.DragAndDropPermissions import android.view.DragEvent import android.view.View import android.view.View.DragShadowBuilder import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.core.view.draganddrop.DragAndDropManagerCompat import androidx.core.view.draganddrop.DropHelper class DragAndDropWithViews : AppCompatActivity() { private lateinit var textView1: TextView private lateinit var textView2: TextView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_drag_and_drop_with_views) textView1 = findViewById(R.id.text_view_1) textView2 = findViewById(R.id.text_view_2) // Set touch listener for drag textView1.setOnLongClickListener { // Create ClipData for the drag item val clipData = ClipData("text", arrayOf(MIMETYPE_TEXT_PLAIN), ClipData.Item(it.tag as CharSequence)) // Start the drag and drop operation it.startDragAndDrop( clipData, DragShadowBuilder(it), it, 0 ) true } // Set drag listener for drop target textView2.setOnDragListener { view, dragEvent -> when (dragEvent.action) { DragAndDropManagerCompat.ACTION_DRAG_STARTED -> { // Indicates that a drag operation has started. true } DragAndDropManagerCompat.ACTION_DRAG_ENTERED -> { // Indicates that a drag shadow has entered the bounds of a view. view.alpha = 0.5f true } DragAndDropManagerCompat.ACTION_DRAG_LOCATION -> { // Indicates that a drag shadow is moving within the bounds of a view. true } DragAndDropManagerCompat.ACTION_DRAG_EXITED -> { // Indicates that a drag shadow has exited the bounds of a view. view.alpha = 1.0f true } DragAndDropManagerCompat.ACTION_DROP -> { // Indicates that a drag shadow has been dropped within the bounds of a view. val item = dragEvent.clipData.getItemAt(0) val draggedData = item.text.toString() (view as TextView).text = draggedData view.alpha = 1.0f true } DragAndDropManagerCompat.ACTION_DRAG_ENDED -> { // Indicates that a drag operation has ended. view.alpha = 1.0f true } else -> { false } } } } } ``` -------------------------------- ### Audio Manager Communication Sample Source: https://github.com/android/platform-samples/blob/main/samples/connectivity/audio/README.md Shows how to use the audio manager to manage the communication device, particularly useful during VoIP calls. Requires appropriate Android permissions. ```kotlin package com.example.platform.connectivity.audio import android.content.Context import android.media.AudioManager import androidx.appcompat.app.AppCompatActivity import android.os.Bundle class AudioCommsSample : AppCompatActivity() { private lateinit var audioManager: AudioManager override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager } override fun onResume() { super.onResume() // Example: Set to speakerphone mode audioManager.isSpeakerphoneOn = true } override fun onPause() { super.onPause() // Example: Restore default behavior (e.g., turn off speakerphone) audioManager.isSpeakerphoneOn = false } } ``` -------------------------------- ### Basic MotionLayout Animation Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/constraintlayout/README.md Demonstrates a basic animation using MotionLayout. This snippet is suitable for simple transitions between two states. ```xml ``` ```xml ``` -------------------------------- ### Accepting Rich Media Content Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/draganddrop/README.md Showcases handling rich media content using the `RichContentReceiver` API, which supports drag-and-drop, keyboard, and clipboard operations. ```kotlin package com.example.platform.ui.draganddrop import android.os.Build import android.os.Bundle import android.util.Log import android.view.View import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ContentInfoCompat import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.draganddrop.DropHelper class DragAndDropRichContentReceiverFragment : AppCompatActivity() { private lateinit var richContentReceiverView: TextView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_drag_and_drop_rich_content_receiver) richContentReceiverView = findViewById(R.id.rich_content_receiver_view) // Set up the RichContentReceiver ViewCompat.setOnReceiveContentListener(richContentReceiverView) { view, payload -> Log.d("RichContentReceiver", "Received content") // Check if the payload contains text val text = payload.getText(view.context) if (text != null) { (view as TextView).text = text // Return the payload to indicate it was handled return@setOnReceiveContentListener payload } // Handle other types of content if necessary (images, etc.) // For this example, we only handle text. null // Return null if the content is not handled } } } ``` -------------------------------- ### Basic MotionLayout Animation (No Auto Complete) Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/constraintlayout/README.md Illustrates a basic MotionLayout animation where the animation does not automatically complete on swipe. Use this when manual control over animation completion is desired. ```xml ``` ```xml ``` -------------------------------- ### Reacting to IME Visibility Changes with WindowInsetsAnimationCompat Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/window-insets/README.md Implement a WindowInsetsAnimationCompat.Callback to automatically adjust UI elements when the IME appears or disappears. This provides a smooth user experience by making views move in unison with the IME. Graceful degradation is handled for API levels below 30. ```java public class TranslateDeferringInsetsAnimationCallback : WindowInsetsAnimationCompat.Callback { private val view: View private var startTop: Int = 0 private var endTop: Int = 0 constructor(view: View) : super(DISPATCH_MODE_CONTINUE_ON_SUBపంచ) { this.view = view } override fun onPrepare(controller: WindowInsetsAnimationControllerCompat?) { super.onPrepare(controller) val insets = view.rootWindowInsets startTop = insets.getInsets(WindowInsetsCompat.Type.ime()).top } override fun onProgress( insets: WindowInsetsCompat, runner: WindowInsetsAnimationCompat.InterpolatorRunner ): WindowInsetsCompat { val imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime()) val fraction = runner.fraction val currentTop = startTop + ((imeInsets.top - startTop) * fraction).roundToInt() view.updateLayoutParams { topMargin = currentTop } return insets } override fun onEnd(controller: WindowInsetsAnimationControllerCompat?) { super.onEnd(controller) } override fun onCancel(controller: WindowInsetsAnimationControllerCompat?) { super.onCancel(controller) } } ``` -------------------------------- ### MotionLayout with CoordinatorLayout Integration (2) Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/constraintlayout/README.md Presents another scenario of integrating MotionLayout with CoordinatorLayout, likely demonstrating different header behaviors or scroll effects. ```xml ``` ```xml ``` -------------------------------- ### License Information Source: https://github.com/android/platform-samples/blob/main/samples/connectivity/bluetooth/ble/README.md This is the Apache 2.0 license text. ```text Copyright 2022 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ``` -------------------------------- ### App Widgets License Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/appwidgets/README.md Contains the Apache License, Version 2.0, governing the use of the App Widgets sample code. ```text Copyright 2023 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ``` -------------------------------- ### MotionLayout Keyframe Cycle Animation Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/constraintlayout/README.md Demonstrates creating a cyclical animation using keyframes in MotionLayout. This is useful for animations that repeat or loop. ```xml ``` ```xml ``` -------------------------------- ### Linkify Text with LinkifyCompat Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/text/README.md Utilize `LinkifyCompat` to automatically create clickable links for email addresses, phone numbers, and URLs within TextViews. Custom patterns can also be defined using regular expressions. ```java LinkifyCompat.addLinks(textView, LinkifyCompat.ALL); ``` -------------------------------- ### MotionLayout Keyframe Position Animation Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/constraintlayout/README.md Demonstrates animating an object's position along a path using keyframes in MotionLayout. This allows for precise control over the animation's trajectory. ```xml ``` ```xml ``` -------------------------------- ### Custom Progress API Animation Handling Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/predictiveback/README.md Implements custom back progress animations using the Progress API. Handles swipe edge, progress, and scaling for visual feedback during predictive back gestures. ```kotlin override fun onViewCreated(view: View, savedInstanceState: Bundle?) { "..." val windowWidth = requireActivity().windowManager.currentWindowMetrics.bounds.width() val maxXShift = windowWidth / 20 val predictiveBackCallback = object: OnBackPressedCallback(enabled=false) { override fun handleOnBackProgressed(backEvent: BackEventCompat) { when (backEvent.swipeEdge) { BackEventCompat.EDGE_LEFT -> binding.box.translationX = backEvent.progress * maxXShift BackEventCompat.EDGE_RIGHT -> binding.box.translationX = -(backEvent.progress * maxXShift) } binding.box.scaleX = 1F - (0.1F * backEvent.progress) binding.box.scaleY = 1F - (0.1F * backEvent.progress) } override fun handleOnBackPressed() { // your back handling logic } override fun handleOnBackCancelled() { binding.box.scaleX = 1F binding.box.scaleY = 1F binding.box.translationX = 0F } } requireActivity().onBackPressedDispatcher.addCallback( this.viewLifecycleOwner, predictiveBackCallback ) } ``` -------------------------------- ### Cross-fragment Animation with MaterialSharedAxis Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/predictiveback/README.md Implement cross-fragment animations using MaterialSharedAxis. Configure exit/reenter transitions for the exiting fragment and enter/return transitions for the entering fragment. This transition requires a change in fragment visibility or addition/removal to trigger. ```kotlin // FragmentA.kt override fun onCreateView(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, /* forward= */ true) reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, /* forward= */ false) } ``` ```kotlin // FragmentB.kt override fun onCreateView(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, /* forward= */ true) returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, /* forward= */ false) } ``` -------------------------------- ### Navigation Component Fragment Transitions Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/predictiveback/README.md Defines default enter, exit, pop enter, and pop exit animations for fragment transitions using the navigation component. ```xml ``` -------------------------------- ### MotionLayout Keyframe Interpolation Animation Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/constraintlayout/README.md Illustrates animating an object's properties with different interpolation curves using keyframes in MotionLayout. This allows for varied animation pacing. ```xml ``` ```xml ``` -------------------------------- ### License Information Source: https://github.com/android/platform-samples/blob/main/samples/privacy/permissions/README.md This section provides the Apache License 2.0 details for the code. ```plaintext Copyright 2023 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ``` -------------------------------- ### MotionLayout with ImageFilterView Animation Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/constraintlayout/README.md Demonstrates animating an ImageFilterView using MotionLayout. This allows for applying various image filters and animating their properties. ```xml ``` ```xml ``` -------------------------------- ### Drag and Drop Across Apps Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/draganddrop/README.md Demonstrates drag-and-drop functionality across different applications in multi-window mode on Android. ```kotlin package com.example.platform.ui.draganddrop import android.content.ClipData import android.content.ClipDescription.MIMETYPE_TEXT_PLAIN import android.os.Build import android.os.Bundle import android.view.DragEvent import android.view.View import android.view.View.DragShadowBuilder import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.core.view.draganddrop.DragAndDropManagerCompat class DragAndDropMultiWindow : AppCompatActivity() { private lateinit var textView1: TextView private lateinit var textView2: TextView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_drag_and_drop_multi_window) textView1 = findViewById(R.id.text_view_1) textView2 = findViewById(R.id.text_view_2) // Set touch listener for drag textView1.setOnLongClickListener { val clipData = ClipData("text", arrayOf(MIMETYPE_TEXT_PLAIN), ClipData.Item(it.tag as CharSequence)) it.startDragAndDrop( clipData, DragShadowBuilder(it), it, 0 ) true } // Set drag listener for drop target textView2.setOnDragListener { view, dragEvent -> when (dragEvent.action) { DragAndDropManagerCompat.ACTION_DRAG_STARTED -> { true } DragAndDropManagerCompat.ACTION_DRAG_ENTERED -> { view.alpha = 0.5f true } DragAndDropManagerCompat.ACTION_DRAG_LOCATION -> { true } DragAndDropManagerCompat.ACTION_DRAG_EXITED -> { view.alpha = 1.0f true } DragAndDropManagerCompat.ACTION_DROP -> { val item = dragEvent.clipData.getItemAt(0) val draggedData = item.text.toString() (view as TextView).text = draggedData view.alpha = 1.0f true } DragAndDropManagerCompat.ACTION_DRAG_ENDED -> { view.alpha = 1.0f true } else -> { false } } } } } ``` -------------------------------- ### Fragment Transaction with Custom Animations Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/predictiveback/README.md This fragment handles the click event to trigger a fragment transaction with custom enter, exit, popEnter, and popExit animations using setCustomAnimations. Ensure reordering is allowed and add to the back stack. ```kotlin // PBSetCustomAnimationsFirstFragment.kt override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, ): View { _binding = FragmentSetCustomAnimationsBinding .inflate(inflater, container, false) binding.box.setOnClickListener { parentFragmentManager.commit { setCustomAnimations( android.R.animator.fade_in, // enter android.R.animator.fade_out, // exit android.R.animator.fade_in, // popEnter android.R.animator.fade_out) // popExit replace(R.id.fragment_container,PBSetCustomAnimationsSecondFragment()) setReorderingAllowed(true) addToBackStack(null) } } return binding.root } ``` -------------------------------- ### Custom AndroidX Transition for Predictive Back Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/predictiveback/README.md Define a custom transition set for predictive back gestures. This involves creating an OnBackPressedCallback to control the transition based on back event progress and completion. Ensure the transition is applied to a container view. ```kotlin class MyFragment : Fragment() { val transitionSet = TransitionSet().apply { addTransition(Fade(Fade.MODE_OUT)) addTransition(ChangeBounds()) addTransition(Fade(Fade.MODE_IN)) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val callback = object : OnBackPressedCallback(enabled = false) { var controller: TransitionSeekController? = null override fun handleOnBackStarted(backEvent: BackEvent) { // Create the transition controller = TransitionManager.controlDelayedTransition( // textContainer is a FrameLayout containing the shortText and longText TextViews binding.textContainer, transitionSet ) changeTextVisibility(ShowText.SHORT) } override fun handleOnBackProgressed(backEvent: BackEvent) { // Play the transition as the user swipes back if (controller?.isReady == true) { controller?.currentFraction = backEvent.progress } } override fun handleOnBackPressed() { // Finish playing the transition when the user commits back controller?.animateToEnd() this.isEnabled = false } override fun handleOnBackCancelled() { // If the user cancels the back gesture, reset the state transition(ShowText.LONG) } } binding.shortText.setOnClickListener { transition(ShowText.LONG) callback.isEnabled = true } this.requireActivity().onBackPressedDispatcher.addCallback(callback) } private fun transition(showText: ShowText) { TransitionManager.beginDelayedTransition( binding.textContainer, transitionSet ) changeTextVisibility(showText) } enum class ShowText { SHORT, LONG } private fun changeTextVisibility(showText: ShowText) { when (showText) { ShowText.SHORT -> { binding.shortText.isVisible = true binding.longText.isVisible = false } ShowText.LONG -> { binding.shortText.isVisible = false binding.longText.isVisible = true } } } } ``` -------------------------------- ### Shared Element Fragment Transition Configuration Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/predictiveback/README.md Configures enter and shared element enter transitions for a fragment. Specifying `enterTransition` is necessary alongside `sharedElementEnterTransition` to enable predictive back gesture. ```kotlin override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enterTransition = AutoTransition() sharedElementEnterTransition = AutoTransition() } ``` -------------------------------- ### License Information Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/draganddrop/README.md Contains the Apache License, Version 2.0, governing the use of the software. ```plaintext Copyright 2023 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. you may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ``` -------------------------------- ### Drag and Drop in Jetpack Compose Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/draganddrop/README.md Showcases drag-and-drop implementation within a Jetpack Compose UI. ```kotlin package com.example.platform.ui.draganddrop import android.os.Build import android.os.Bundle import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.material3.Text import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.core.view.draganddrop.DragAndDropManagerCompat import androidx.core.view.draganddrop.DropHelper class DragAndDropUsingCompose : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { DragAndDropScreen() } } } @Composable fun DragAndDropScreen() { var droppedText by remember { mutableStateOf("Drop here") } Column( modifier = Modifier .fillMaxSize() .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Box( modifier = Modifier .size(100.dp) .background(Color.Blue) .dragSource( // Make this Box a drag source clipData = { androidx.core.view.draganddrop.ClipData( "text", arrayOf(androidx.core.view.draganddrop.ClipDescription.MIMETYPE_TEXT_PLAIN), androidx.core.view.draganddrop.ClipData.Item("Dragged Item") ) }, shadowBuilder = { androidx.core.view.draganddrop.DragShadowBuilder(this@Box) }, flags = 0 ) ) Spacer(modifier = Modifier.height(32.dp)) Box( modifier = Modifier .size(150.dp) .background(Color.Gray) .dropTarget { event -> // Make this Box a drop target if (event.action == DragAndDropManagerCompat.ACTION_DROP) { val item = event.clipData.getItemAt(0) droppedText = item.text.toString() Log.d("DragDropCompose", "Dropped: ${droppedText}") true } else { false } }, contentAlignment = Alignment.Center ) { Text(text = droppedText) } } } ``` -------------------------------- ### Controlling IME Visibility with WindowInsetsAnimationControllerCompat Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/window-insets/README.md Utilize WindowInsetsAnimationControllerCompat to animate the IME on and off screen as part of a scroll gesture. This is particularly useful for custom scrolling views that over-scroll, allowing the IME to be controlled directly by the user's interaction. Requires AndroidX Core 1.5.0+ and functions on devices with Android 11 or newer. ```java class InsetsAnimationLinearLayout : LinearLayout { private var controller: WindowInsetsAnimationControllerCompat? = null constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) init { setOnApplyWindowInsetsListener { v, insets -> val imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime()) val insetTop = imeInsets.top val fraction = if (insetTop == 0) 0f else 1f if (controller == null) { controller = WindowInsetsControllerCompat(v.rootWindowInsets, v) } controller?.control(WindowInsetsCompat.Type.ime(), fraction) // Consume the IME insets to prevent them from being passed further down the view hierarchy v.rootWindowInsets = insets.consume(WindowInsetsCompat.Type.ime()) insets.consumeDisplayCutout() // Consume other insets if necessary } } } ``` ```java class InsetsAnimationTouchListener(private val controller: WindowInsetsAnimationControllerCompat) : View.OnTouchListener { private var initialY: Float = 0f private var initialBottom: Int = 0 override fun onTouch(v: View, event: MotionEvent): Boolean { val imeInsets = v.rootWindowInsets.getInsets(WindowInsetsCompat.Type.ime()) val currentBottom = imeInsets.bottom when (event.action) { MotionEvent.ACTION_DOWN -> { initialY = event.y initialBottom = currentBottom return true } MotionEvent.ACTION_MOVE -> { val deltaY = event.y - initialY val newBottom = (initialBottom - deltaY).toInt() val fraction = newBottom.toFloat() / v.height // Assuming view height represents max IME height controller.control(WindowInsetsCompat.Type.ime(), fraction.coerceIn(0f, 1f)) return true } MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { // Optionally, animate to a final state or reset return true } } return false } } ``` -------------------------------- ### Drag and Drop with Jetpack Library Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/draganddrop/README.md Utilizes the Jetpack Drag and Drop Library for implementing drag-and-drop functionality in Android applications. ```kotlin package com.example.platform.ui.draganddrop import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.core.view.draganddrop.DropHelper import androidx.fragment.app.commit class DragAndDropWithHelper : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_drag_and_drop_with_helper) if (savedInstanceState == null) { supportFragmentManager.commit { setReorderingAllowed(true) add(R.id.fragment_container_view, DragDropHelperFragment()) } } } } ``` -------------------------------- ### MotionLayout with Custom Attribute Animation Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/constraintlayout/README.md Shows how to animate custom attributes within a MotionLayout transition. This is useful for animating properties not directly supported by standard view attributes. ```xml ``` ```xml ``` -------------------------------- ### Build Spanned String with core-ktx Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/text/README.md Use `buildSpannedString` from the core-ktx library for efficient creation of rich text with spans. Ensure the core-ktx library is included in your project dependencies. ```kotlin val spannedString = buildSpannedString { append("This is normal text.") append(" This is bold.", SpanStyle(fontWeight = FontWeight.Bold)) append(" This is italic.", SpanStyle(fontStyle = FontStyle.Italic)) } ``` -------------------------------- ### Override Activity Transitions Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/predictiveback/README.md Use `overrideActivityTransition` for custom cross-activity animations. It expects animation resources but recommends using animators and AndroidX transitions. ```kotlin override fun onCreate(savedInstanceState: Bundle?) { "..." overrideActivityTransition( OVERRIDE_TRANSITION_OPEN, android.R.anim.fade_in, 0 ) overrideActivityTransition( OVERRIDE_TRANSITION_CLOSE, 0, android.R.anim.fade_out ) } ``` -------------------------------- ### Configure Line Break Word Style Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/text/README.md Control line breaking behavior for languages like Japanese and Chinese using `android:lineBreakWordStyle`. Set to `"phrase"` to prevent line breaks within phrases (bunsetsu). This feature requires the device locale to be set appropriately. ```xml ``` -------------------------------- ### Enable Hyphenation in TextView Source: https://github.com/android/platform-samples/blob/main/samples/user-interface/text/README.md Apply automatic hyphenation to TextViews using the `android:hyphenationFrequency` attribute. For Android 13 (API 33) and higher, `fullFast` and `normalFast` offer improved performance. ```xml ```