AI 资讯
CSS Architecture
Responsive CSS: From Mobile-First Design to Modern Styling Responsive design is about creating websites that work well across mobile, tablet, and desktop screens. In this post, I learned some important techniques for building responsive and maintainable CSS. 1. Mobile-First Media Queries Mobile-first means writing the base CSS for smaller screens first and then enhancing the layout for larger screens. /* Mobile */ .card { width : 100% ; } /* Tablet */ @media ( min-width : 768px ) { .card { width : 70% ; } } /* Desktop */ @media ( min-width : 1024px ) { .card { width : 50% ; } } The main idea is: Mobile → Tablet → Desktop min-width is commonly used for mobile-first development because styles are progressively added as the screen gets larger. min-width vs max-width min-width : applies styles when the screen is at least the specified width. max-width : applies styles when the screen is at most the specified width. For example: @media ( max-width : 768px ) { h1 { font-size : 20px ; } } One important lesson I learned: CSS media queries belong inside <style> or a CSS file, not inside <script> . 2. Fluid Typography Fixed font sizes don't always work well across different screen sizes. Fluid typography allows text to adapt to the viewport. rem rem is relative to the root font size. h1 { font-size : 2rem ; } If the root size is 16px, 2rem is 32px. vw vw is relative to the viewport width. h1 { font-size : 5vw ; } However, using only vw can make text too small or too large. clamp() clamp() provides a minimum, flexible value, and maximum: h1 { font-size : clamp ( 1.5rem , 4vw , 3rem ); } This allows the font size to grow smoothly while keeping it within limits. 3. Responsive Images Images can consume a lot of bandwidth, so responsive images help browsers choose an appropriate image for the device. srcset <img src= "small.jpg" srcset= " small.jpg 400w, medium.jpg 800w, large.jpg 1200w" sizes= "100vw" alt= "Mountain" > srcset provides multiple image sizes, allowing the browser to
开发者
This weekend is all about performance tuning (or attempting to) my new game before pushing to mobile platforms. Runs great on desktop but I know I can do better on mid to low mobile devices, especially Android.
AI 资讯
Build map guidance that follows the user without blocking pinch-to-zoom
A navigation map should help the user move through the world, not fight every gesture they make. I recently hit a deceptively simple bug while building field guidance in a React Native / Expo app: the route rendered correctly and the camera followed the current position, but users could not meaningfully zoom or pan while walking. They could pinch the map, but the next location update snapped the camera back to a fixed zoom. The map looked active. The experience felt broken. The cause: two camera owners The implementation combined two useful features: followsUserLocation={true} on the native map. animateCamera(...) after every location update, using a fixed walking zoom and pitch. Each feature was reasonable on its own. Together, they gave the camera two automatic owners and the user none. A pinch gesture changed the zoom for a fraction of a second. Then a GPS update arrived and our effect applied the navigation camera again. On iOS, native user-follow behavior added another layer of camera control. A better model: follow mode and explore mode The fix was not to stop navigation. Route progress, distance, bearing, breadcrumb recording and off-route detection should all continue regardless of what the user does with the map. Only the camera behavior should change. We now keep a small piece of local UI state: const [ cameraFollowing , setCameraFollowing ] = useState ( navigationActive ); useEffect (() => { if ( ! navigationActive || ! cameraFollowing || bearing == null ) return ; mapRef . current ?. animateCamera ( walkingCamera ( currentCoordinate , bearing ), { duration : 480 }, ); }, [ currentCoordinate , bearing , navigationActive , cameraFollowing ]); The native follow prop uses the same state: < MapView showsUserLocation followsUserLocation = { navigationActive && cameraFollowing } onTouchStart = { () => { if ( navigationActive ) setCameraFollowing ( false ); } } /> As soon as the user touches the map, the camera enters explore mode. Pinch, pan and rotation work n
AI 资讯
Samsung’s Z Fold 8 Ultra is more of the same, but better than ever
What makes the Samsung Galaxy Z Fold 8 Ultra so Ultra? Samsung's first foldable with the Ultra name isn't a souped-up version of the regular Fold 8, as you might expect. Where the Z Fold 8 is squat and wide, the Fold 8 Ultra retains the thin outer screen and square inner panel of the […]
AI 资讯
Architectural Excellence in Modern Android: Jetpack Compose, MVVM, and Clean Code Principles
Introduction: Moving Beyond Traditional XML Layouts Android development has evolved significantly. The days of managing complex XML layouts with findViewById or basic View Binding are fading fast. Modern Android development demands clean architecture, reactive state management, and declarative UI tools like Jetpack Compose. In this deep dive, we will explore how to structure scalable, maintainable, and testable native Android applications using the Model-View-ViewModel (MVVM) architecture alongside Jetpack Compose. Why MVVM with Jetpack Compose? The Model-View-ViewModel pattern provides a clean separation of concerns between your business logic and presentation layer: Model: Handles data sources (Local database via Room, Remote API calls via Retrofit). ViewModel: Preserves state during configuration changes, holds business logic, and exposes state observables. View (Compose): Declarative UI composables that automatically re-compose (re-render) when the underlying state changes. Using Jetpack Compose alongside MVVM eliminates UI boilerplate code, avoids memory leaks associated with traditional views, and simplifies dynamic UI state management. Layered Architecture Overview The Data Layer The data layer is responsible for retrieving and storing data from external or local sources. It uses the Repository Pattern to expose a clean API to the rest of the app: Kotlin interface UserRepository { suspend fun getUserProfile(userId: String): Result } class UserRepositoryImpl( private val apiService: ApiService, private val userDao: UserDao ) : UserRepository { override suspend fun getUserProfile(userId: String): Result { // Handle network requests, local caching, and fallback strategies } } The Domain Layer (Optional for Large Apps) Contains Use Cases (Interactors) that encapsulate single pieces of business logic. This ensures that ViewModels remain lightweight and focused strictly on managing UI state. The UI Layer (ViewModel + Composables) The UI layer reads state exposed by
AI 资讯
The Privacy Summary Screen — 60 Minutes of Design With Outsized Impact
Most mobile apps ship a privacy policy as a link that opens Safari. A smaller number ship an in-app rendered policy. A tiny minority ship what I think is the single highest-leverage privacy screen: a summary that mirrors your Nutrition Label in plain language, designed to be read. Why it's high-leverage The privacy summary sits at the intersection of three concerns: Users read it before granting sensitive permissions. Especially for camera, contacts, location, and health data. App Store reviewers check it exists and matches your store listing. Regulators (GDPR, CCPA) reward it. Clarity is a compliance signal, not a legal defense — but it's what an investigator asks for first. Sixty minutes of design work. Meaningful trust dividends. Often the difference between first-submission approval and a rejection loop. What to include The privacy summary should mirror your Privacy Nutrition Label but with real language humans can parse: Each data category you collect — displayed as a card or a row, with a clear icon. Why you collect it — one line, plain language. "So you can log in on another device," not "for authentication purposes." Where it's used — is it stored on our servers, shared with third parties, only on your device? Be specific. How to opt out or delete it — a link or a button to the settings page where the user can act on that category. Six to eight cards, one per data category. No more. Visual patterns that read as trustworthy Design choices that consistently score high in user-testing for trust signal: Real language, not legalese. "We store your email address so you can log in" beats "Personal identifiers are retained for authentication purposes." Muted, confident colors. No warning reds, no compliance yellows. A neutral surface with soft accent for the data-category icons. Readable typography. 16pt body, generous line-height (1.5x), enough paragraph spacing that scanning is easy. Icons per category (not just text). A camera icon for camera data, a location pin
AI 资讯
SpaceX claims Starlink Mobile will be better than AT&T, T-Mobile, and Verizon
SpaceX won't build large cell towers but plans small base stations across US.
产品设计
SpaceX is coming for T-Mobile, AT&T and Verizon
SpaceX is preparing to build a terrestrial mobile network to "acquire quite a few" of the customers now subscribed to T-Mobile, AT&T, and Verizon. The message to compete head-to-head with the US carriers was delivered by SpaceX president Gwynne Shotwell and CEO Elon Musk during the Q&A section of the company's first earnings call. "The […]
AI 资讯
T-Mobile’s $0-down financing plan bundles taxes and fees
T-Mobile is launching a new financing option that will allow you to pay for a device, taxes, and fees over 36 months. In an update on Tuesday, T-Mobile says its new Equipment Installment Plan (EIP) Flex 36 requires no upfront payment and will come with a 0 percent APR for a limited time. Even if […]
AI 资讯
A Lightweight Rich Text Component Without a Web View
PR #5421 adds RichTextComponent , a read-only component for formatted application text. It supports headings, inline styles, lists, links, and images without embedding a web view. What is Codename One? Codename One is an open-source framework for building native iOS, Android, desktop, and web apps from a single Java or Kotlin codebase. Learn more at codenameone.com . A SpanLabel applies one style to wrapped text. A BrowserComponent renders a complete web page. RichTextComponent covers formatted document content between those two cases and participates in ordinary Codename One layout. Rich text inside a scrollable container A common screen mixes formatted text with buttons, images, forms, and other Codename One components inside one scrollable container. A BrowserComponent is a poor fit for that layout because it owns a rectangular native surface and its own page viewport. The browser's document height does not naturally become the height of a child inside the parent Codename One layout. RichTextComponent measures wrapped runs for the width it receives and reports the corresponding height. In the default SizeMode.SHRINK , it behaves like a SpanLabel : the parent container scrolls the rich text together with the surrounding components. SizeMode.SCROLL is available when the rich text should keep an assigned height and scroll its own content. The read-only view and editor agree on paragraph attributes, inline styles, links, image runs, and wrapping because they do not maintain competing renderers. Supply the format you already have HTML is not the only input: RichTextComponent view = new RichTextComponent (); view . setMarkdown ( "# Trip summary\n\n" + "Departs **09:40**, arrives *11:15*. " + "See the [itinerary](app://itinerary).\n\n" + "- Window seat\n" + "- Carry-on only" ); form . add ( view ); setContent(...) accepts RichTextFormat.HTML , MARKDOWN , ASCIIDOC , or RTF . The model covers headings, emphasis, inline code, links, images, lists, quotes, literal blocks, p
AI 资讯
How I Made Features in a Large Flutter App Actually Removable
"Just delete the features you don't need" is the easiest thing in the world to write in a README, and the hardest to make true. I hit this building a Flutter app with six verticals in one codebase — marketplace, ride-hailing, car rentals, social feed, chat, wallet. Deleting one should have been simple. It wasn't, because every feature had tendrils: a route in the central route table a tab hardcoded in the app shell a button on the home screen a service registered in main() Remove the feature folder and you get a wall of compile errors from files that have nothing to do with it. Here's what actually worked. Make three things data instead of code 1. Routes Each feature exposes its own routes from its own folder: class WalletModule extends AppModule { const WalletModule (); @override String get id = > 'wallet' ; @override List < GetPage > get pages = > [ GetPage ( name: AppRoutes . wallet , page: () = > const WalletScreen ()), ]; } The app's route table becomes a composition: static final routes = < GetPage >[ .. . _centralRoutes , .. . ModuleRegistry . pages , ]; Adding or removing a feature stops being an edit to a shared file. It's one line in a registry. 2. Bottom-navigation tabs This one surprised me. My app shell imported the feed widget directly: // before — the always-present shell depends on an optional feature import '../feed/feed_tab.dart' ; The shell ships in every build. That import meant the social feature could never be removed. So a tab became a small data class that a feature contributes: class ShellTab { final String id ; final int order ; // core tabs use 10/30/40 final IconData icon ; final String labelKey ; final Widget Function () builder ; } Social contributes its tab at order 20, slotting between home and alerts without the shell knowing it exists. The shell merges its own tabs with ModuleRegistry.shellTabs and sorts. 3. Entry points Home screens linked to feature screens with Get.toNamed(...) . Named routes are already decoupled — no import nee
AI 资讯
Pure Codename One Text Editing Without Native Overlays
PR #5386 adds a pure Codename One text-editing path. EditField , RichTextArea , and CodeEditor can now keep their document, selection, and painting inside the lightweight UI while each port supplies keyboard and input-method events. What is Codename One? Codename One is an open-source framework for building native iOS, Android, desktop, and web apps from a single Java or Kotlin codebase. Learn more at codenameone.com . Text input must handle virtual keyboards, hardware keys, autocorrect, dictation, marked text from an input method editor, bidirectional text, selection, clipboard formats, and accessibility geometry. Codename One traditionally delegates that work to a native platform field placed over the lightweight component during editing. The overlay remains the default for TextField and TextArea . It can create a small visual jump, and it cannot participate in lightweight painting for syntax highlights, rich runs, masks, inline images, or a custom selection model. The port sends text operations instead of key codes A soft keyboard does not type keys. It commits words, replaces a marked composition range, deletes text around the caret, and changes selection. Dictation may insert a sentence without producing one key event. The new TextInputClient contract models those operations: commitText(...) inserts final text. setComposingText(...) replaces the active marked-text range. finishComposing() accepts that range. deleteSurroundingText(...) implements virtual-keyboard deletion. onKeyCommand(...) carries navigation, selection, clipboard, undo, and redo. Geometry queries locate the caret and selection for candidate windows and accessibility. All offsets use UTF-16 indices. That matches Java String , Android Editable , and Apple string APIs. The document normalizes line endings before it updates selection, undo history, formatting runs, or the state returned to the platform. The port still owns the keyboard session. Codename One owns the document and what appears on scr
开发者
Palworld’s expanding to mobile with a new MMORPG
After its 1.0 launch last month, Palworld is coming to iOS and Android with a new open-world MMORPG launching later this year, Polygon reports. Garena, the developer behind the new game, says in its announcement that Palworld Online "reimagines the depth, freedom, and scale of the original PC survival creature-collecting title for mobile." The core […]
AI 资讯
Architecting a Reliable Background Service for Android Sound Automation
It happened during a medical appointment. I was sitting in the quiet waiting room, my thoughts occupied by the upcoming consultation, when my phone erupted with a loud, aggressive ringtone. The entire room turned to look at me, and I fumbled to silence it, accidentally hitting the volume up button instead of the mute toggle in my panic. I felt that specific, burning embarrassment that comes from being the person who disrupts a quiet space. I realized then that I had spent years writing code for others, yet I couldn't solve my own basic problem of managing my phone's profile. We live in a world of constant notifications and persistent demands on our attention. The real friction isn't just that phones ring; it's that we are expected to remember to manually toggle settings in a dozen different contexts every single day. Whether it is a classroom, a house of worship, or a professional meeting, the human element of remembering to flip a switch is the point of failure. I wanted an app that handled this silently, without me having to open an interface or even think about the current state of my device. I needed a system that functioned as an extension of my environment rather than an additional task. Building Muffle required me to confront the reality of modern Android background execution. Initially, I thought a simple BroadcastReceiver listening for time changes or geofence triggers would suffice. I was wrong. As soon as the phone entered Doze mode—the power-saving state introduced in Android 6.0—my triggers would either be delayed significantly or killed entirely by the system’s restrictive task scheduler. I had to architect a solution that could survive these aggressive optimizations while remaining battery-efficient. The core of the application resides in a ForegroundService that maintains a persistent notification. While many developers avoid these because of the UI footprint, it is the only way to signal to the OS that your process is performing an essential, user-v
AI 资讯
Foldables are sort of boring now — and that’s great news for Apple
This is The Stepback, a weekly newsletter breaking down one essential story from the tech world. For more on smartphones and Android, follow Dominic Preston. The Stepback arrives in our subscribers' inboxes on Sunday at 8AM ET. Opt in for The Stepback here. How it started Believe it or not, it didn't all start with […]
AI 资讯
You could be taking way better photos on your phone
Your smartphone photos can look way better. If you're willing to put in a little extra work, use third party apps and spend a bit of time editing, it's possible to take photos that - under the right circumstances - can rival dedicated digital cameras. I post a lot of smartphone photos online, and "How […]
AI 资讯
For the First Time, Zoox Can Charge People for Rides in Its Steering-Wheel-Free Robotaxis
The temporary exemption from federal safety standards will let Amazon’s Zoox launch a real, paid robotaxi service in Las Vegas.
开发者
Samsung's mobile division posts first-ever loss due to soaring memory prices
Samsung's mobile and chip divisions are going in opposite directions, profit-wise.
AI 资讯
Qualcomm is raising phone chip prices starting September 1st
RAMageddon won't be the only reason your next phone costs more - Qualcomm is about to raise prices on all its processors, as well. Qualcomm CEO Cristiano Amon said on Wednesday that "prices are going to go up" on the company's products starting on September 1st, CNBC reports. The price hikes were rumored last week […]
AI 资讯
Port Support You Can Trace Back to a Green Test
“Supported on iOS, Android, desktop, and web” sounds useful until you need one method on one target. Does WebSocket work on watchOS? Which Linux architectures do we build? Was the JavaScript media test green this week, or did somebody update a table six months ago and forget it? What is Codename One? Codename One is an open-source framework for building native iOS, Android, desktop, and web apps from a single Java or Kotlin codebase. Learn more at codenameone.com . PR #5389 turns those questions into the Codename One Port Status page . It maps 49 user-facing feature groups across 10 portability targets to current conformance results, environment data, skip reasons, and the date of the run. The table is an output, not an opinion The HelloCodenameOne suite already exercises APIs and screenshot goldens on Android, iOS, tvOS, watchOS, JavaScript, native Linux, native Windows, and Mac Catalyst. The missing part was a contract that translated thousands of test cases into a stable public vocabulary. The new conformance mapping connects registered tests and screenshots to rows such as networking, media, databases, maps, notifications, input, accessibility, and 3D. CI normalizes each port's result into the same report format. A publishing workflow writes the latest reports to a data-only branch. The website consumes those reports and renders the matrix. The page currently renders 490 feature cells. Ten targets appear because architectures and renderer variants matter. iOS Metal and legacy OpenGL are separate evidence paths. Windows x64 and ARM64 are separate. Linux x64 and ARM64 are separate. JavaSE is deliberately excluded from the public portability matrix. It is the simulator and development runtime, not one of the deployed native targets the table is meant to prove. A green cell has a chain of evidence Each status report records the commit, environment, registered tests, outcome, duration, and skipped cases. The website data also records the runtime used for browser and