Add Android TV Edition support

- Update AndroidManifest.xml for TV compatibility
- Add ChannelAdapter with D-pad navigation support
- Update MainActivity for TV UI optimization
- Add Android TV specific resources:
  - banner_streamplayer.xml for TV launcher
  - bg_channel_item_selector for focus states
  - values-sw720dp for large screens
  - integers.xml for TV configurations
- Update item_channel.xml for TV navigation
- Remove unused mobile-specific drawable

Features:
- Android TV Leanback support
- D-pad navigation optimization
- TV-optimized layouts and focus management
- Large screen resources for TV displays

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-14 19:00:17 +00:00
parent e6b4d0825b
commit 672774e216
9 changed files with 79 additions and 11 deletions

View File

@@ -8,6 +8,7 @@
<application <application
android:allowBackup="true" android:allowBackup="true"
android:banner="@drawable/banner_streamplayer"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
@@ -27,9 +28,17 @@
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
</application> </application>
<uses-feature
android:name="android.software.leanback"
android:required="false" />
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false" />
</manifest> </manifest>

View File

@@ -43,6 +43,10 @@ public class ChannelAdapter extends RecyclerView.Adapter<ChannelAdapter.ChannelV
listener.onChannelClick(channel); listener.onChannelClick(channel);
} }
}); });
holder.itemView.setOnFocusChangeListener((v, hasFocus) -> {
float scale = hasFocus ? 1.08f : 1f;
v.animate().scaleX(scale).scaleY(scale).setDuration(120).start();
});
} }
@Override @Override

View File

@@ -15,7 +15,8 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);
RecyclerView recyclerView = findViewById(R.id.channel_grid); RecyclerView recyclerView = findViewById(R.id.channel_grid);
recyclerView.setLayoutManager(new GridLayoutManager(this, 3)); recyclerView.setLayoutManager(new GridLayoutManager(this, getSpanCount()));
recyclerView.setHasFixedSize(true);
ChannelAdapter adapter = new ChannelAdapter( ChannelAdapter adapter = new ChannelAdapter(
ChannelRepository.getChannels(), ChannelRepository.getChannels(),
channel -> { channel -> {
@@ -25,5 +26,10 @@ public class MainActivity extends AppCompatActivity {
startActivity(intent); startActivity(intent);
}); });
recyclerView.setAdapter(adapter); recyclerView.setAdapter(adapter);
recyclerView.post(recyclerView::requestFocus);
}
private int getSpanCount() {
return getResources().getInteger(R.integer.channel_grid_span);
} }
} }

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<gradient
android:angle="0"
android:endColor="#FF002766"
android:startColor="#FF0F4C81" />
<corners android:radius="8dp" />
</shape>
</item>
<item>
<bitmap
android:antialias="true"
android:gravity="center"
android:src="@mipmap/ic_launcher" />
</item>
</layer-list>

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#33212121" />
<corners android:radius="12dp" />
<stroke
android:width="1dp"
android:color="#55FFFFFF" />
</shape>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true">
<shape android:shape="rectangle">
<solid android:color="#66FFFFFF" />
<corners android:radius="16dp" />
<stroke
android:width="2dp"
android:color="#FFFFFFFF" />
</shape>
</item>
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="#55FFFFFF" />
<corners android:radius="16dp" />
<stroke
android:width="2dp"
android:color="#FFFFFFFF" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="#33212121" />
<corners android:radius="16dp" />
<stroke
android:width="1dp"
android:color="#55FFFFFF" />
</shape>
</item>
</selector>

View File

@@ -3,7 +3,9 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="6dp" android:layout_margin="6dp"
android:background="@drawable/bg_channel_item" android:background="@drawable/bg_channel_item_selector"
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:orientation="vertical" android:orientation="vertical"
android:padding="16dp"> android:padding="16dp">

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="channel_grid_span">5</integer>
</resources>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="channel_grid_span">3</integer>
</resources>