How to Rapidly Convert an Android Phone App to a Tablet Version in Under 3 Months
This article details a step‑by‑step approach for transforming a modern Android phone application into a tablet‑optimized version within three months, covering UI redesign, activity‑to‑fragment conversion, multi‑process handling, task management, and practical code snippets for a robust Pad‑ification architecture.
How to achieve a fast Pad‑ification of a latest‑version Android app is described, from receiving a large‑scale phone app code to releasing its first tablet version in less than three months.
Project Background
The goal is to adapt the latest phone app (referred to as MyApp) for tablets and large‑screen phones, providing a better experience. Understanding the classic page composition of MyApp and the structural changes after Pad‑ification is the first step.
1. MyApp Classic Page Composition
Typical phone apps use a tab bar with tab content on the main screen, while secondary pages are displayed full‑screen. MyApp follows the same pattern. The left image shows a tab bar (area 1) with tab content (area 2); the right image shows a full‑screen detail page (area 3) opened from the tab content.
Most screens are implemented with Android Activity components; a few hundred activities are present, including Web and picture‑selection processes.
1. MyApp Pad‑ification Design Diagram
After Pad‑ification, the UI is divided into three regions that correspond to the phone’s regions 1, 2, 3. The tab bar moves to the left (region 1), the tab content to the middle (region 2), and the detail page is displayed in region 3 instead of full‑screen.
Exploration Process for Pad‑ifying the Phone App
Based on the classic composition and the new Pad layout, three solution candidates were explored.
Solution 1 – Shrink Activities into a Single Screen
Make the whole design diagram a main Activity (full‑screen) and display new activities (A) reduced in size within region 3.
A‑type Activity inherits Base Activity.
Adjust Base Activity window coordinates (x, width) to fit region 3.
Make A‑type Activity background transparent.
Repeat steps for any Activity opened from A.
Problems discovered:
Activity A remains visible when switching tabs.
All Activities share a single back‑stack, causing back‑key conflicts across tabs.
Solution 2 – Attach Activity Root View to Main Activity
When launching A‑type Activity, obtain its root view via LocalActivityManager and add it to an empty layout in region 3 of the main Activity.
Override startActivity in the main Activity.
Use LocalActivityManager to start A and get its Window object.
Add window.getDecorView() to the main Activity.
Override back‑logic to remove the attached view.
Issues found:
The LocalActivityManager retains a reference to A, preventing its release.
Extracted decorView loses the Activity lifecycle, result handling, and other features.
Solution 3 – Convert Activities to Fragments
Use a plugin‑like approach: wrap each Activity inside a lightweight Fragment that forwards lifecycle calls, without modifying the original Activity code.
Create BasePadActivity that overrides startActivity, instantiates the target Activity, and attaches it to a new MyFragment. MyFragment holds a reference to the Activity instance, calls its lifecycle methods, and uses the Activity’s view as the Fragment’s view.
All Activity‑derived classes inherit BasePadActivity, enabling rapid conversion.
Advantages: fast bulk conversion, preserved logic, and reuse of the main Activity’s context for resources.
Remaining problems:
Custom TitleBar disappears.
All Fragments share a single FragmentManager, causing back‑stack interference across tabs.
Some Activity behaviors (launch mode, onActivityResult, etc.) are not fully simulated.
Multi‑process Activities lose their separate process characteristics.
Final Pad‑ification Architecture
The chosen architecture combines the strengths of the previous attempts:
Convert main‑process Activities to Fragments while keeping their code unchanged.
Fragments simulate Activity behavior (finish, back, result, launch mode).
Use LocalActivityManager to give each tab an independent Fragment stack.
Keep multi‑process Activities unconverted and display them as transparent windows positioned in region 3, preserving their separate processes.
1. Activity‑to‑Fragment Conversion
public class BasePadActivity extends Activity {
@Override
public void startActivityForResult(Intent intent) {
if (isFragment && !isNewProcessActivity()) {
BasePadActivity activity = (BasePadActivity) newInstance(intent);
activity.attachBaseContext(getBaseContext());
activity.onCreate(intent.getExtras());
activity.addMyFragment();
}
}
}
public class MyFragment extends Fragment {
@Override
public View onCreateView() {
return getWindow().getDecorView();
}
@Override
public void onResume() {
super.onResume();
BasePadActivity.this.onResume();
}
@Override
public void onPause() {
super.onPause();
BasePadActivity.this.onPause();
}
}2. Simulating Activity Behaviour in Fragments
Finish:
public void finish() {
if (bActivityToFragment) {
removeTopFragment();
}
}Result handling:
private void removeTopFragment() {
if (popBackStackImmediate()) {
handleSetResult(requestCode, false);
}
}
private void handleSetResult(int requestCode) {
topFragment.onActivityResult(requestCode, resultCode, data);
}Back press:
public void onBackPressed() {
if (isActivityForFragment()) {
if (!handleFragmentBackEvent()) {
finishTopFragment();
}
}
}Launch mode detection:
public boolean hasFlagClearTop(int flags) {
return (flags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0;
}
public boolean hasFlagNewTask(int flags) {
return (flags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0;
}3. Custom TitleBar in Fragments
Override getWindow() to return a custom Window4FragmentTitle that inflates the custom title layout into the Fragment’s decor view.
public Window getWindow() {
if (customWindow == null) {
customWindow = new Window4FragmentTitle(mContext);
}
return customWindow;
}
public class Window4FragmentTitle extends Window {
@Override
public void setContentView(View view, LayoutParams params) {
if (mContentParent == null) installDecor();
mContentParent.addView(view, params);
}
@Override
public void setFeatureInt(int featureId, int value) {
if (featureId != FEATURE_CUSTOM_TITLE) return;
FrameLayout titleContainer = (FrameLayout) findViewById(android.R.id.title);
if (titleContainer != null) {
mLayoutInflater.inflate(value, titleContainer);
}
}
}4. Independent Fragment Stacks per Tab
Each tab hosts its own Activity via LocalActivityManager, and each of those Activities manages a separate FragmentManager, ensuring isolation.
addFrame(Tab1Content.class, mTabs[1]);
addFrame(Tab2Content.class, mTabs[2]);
public void addFrame() {
mTabHost.setup(getLocalActivityManager());
TabSpec tabSpec = mTabHost.newTabSpec("").setIndicator(tab).setContent(new Intent(this, clz));
mTabHost.addTab(tabSpec);
}5. Multi‑Task Split‑Screen for Multi‑Process Activities
Multi‑process Activities remain transparent and are positioned in region 3 using layout parameters, while the left region continues to receive touch events (via FLAG_NOT_TOUCH_MODAL). Different tabs assign distinct taskAffinity values, creating separate tasks with independent back‑stacks.
<activity android:name="BrowserActivity1" android:process=":web" android:taskAffinity="com.tab1.BrowserActivity1" android:theme="@style/Default.Transparent" />
<activity android:name="BrowserActivity2" android:process=":web" android:taskAffinity="com.tab2.BrowserActivity2" android:theme="@style/Default.Transparent" />When a web page is opened, the current tab index determines which activity (with the matching taskAffinity) is launched. Tab switches broadcast an intent that moves the corresponding task to front or back.
public void onTabSelected(int curTabIndex) {
Intent i = new Intent("action");
i.putExtra("cur_Tab_Id", curTabIndex);
sendBroadcast(i);
}
public void onReceive(Context context, Intent intent) {
int tab = intent.getIntExtra(CUR_TAB_ID, -1);
if (tabIndex >= 0 && tabIndex == tab) {
moveTaskToFront(mActivity.getTaskId());
} else {
moveTaskToBack();
}
}Summary
By applying the described architecture, MyApp’s Pad version was launched quickly and has remained stable through multiple iterations. The approach allows developers to modify pages without worrying whether they are backed by an Activity or a Fragment, preserving existing behavior while delivering a tablet‑optimized experience.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Tencent TDS Service
TDS Service offers client and web front‑end developers and operators an intelligent low‑code platform, cross‑platform development framework, universal release platform, runtime container engine, monitoring and analysis platform, and a security‑privacy compliance suite.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
