inflating new layout for BrowseSupportFragment - android-tv

I want to inflate new customized layout for my BrowseSupportFragment on my Android Tv app . I tried many ways but all of them was unsuccessful . The root layout for BrowseSupportFragment is lb_browse_fragment I tried to make new file with the same Id's it has and inflated it as follow but I got error . Can anybody help me on this case ?
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/browse_dummy"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- BrowseFrameLayout serves as root of transition and manages switch between
left and right-->
<androidx.leanback.widget.BrowseFrameLayout
android:focusable="true"
android:focusableInTouchMode="true"
android:descendantFocusability="afterDescendants"
android:id="#+id/browse_frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.leanback.widget.BrowseRowsFrameLayout
android:id="#+id/browse_container_dock"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.leanback.widget.ScaleFrameLayout
android:id="#+id/scale_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.leanback.widget.BrowseRowsFrameLayout>
<!-- Padding needed for shadow -->
<FrameLayout
android:id="#+id/browse_headers_dock"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingEnd="50dp" />
</androidx.leanback.widget.BrowseFrameLayout>
my MainFragment extends BrowseSupportFragment :
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
View view = inflater.inflate(R.layout.browse_fragment_costumized, container, false);
return view;
}

BrowseSupportFragment does a lot of setup in onCreateView, including ensuring overscan is handled and a lot of references are set. You can't use this Fragment in a meaningful way without calling through to onCreateView or you'll break all the assumptions it makes internally.
If you're substantially changing the layout, you shouldn't be using BrowseSupportFragment. If you just need to change some minor things, you can call through to the super onCreateView method and then modify the returned View.

Related

How to create Back Button support in Fragment webview page to go to previous page

In navigation menu of my android app, I add a webview of my blog website. When I click on the menu it opens the blog website in webview. Then I go to specific page of my blog. And when I press back button, The whole webview exit and returned to homepage of my app.
Now, I want to add support of back-key. that means If I press back button It will bring back to my webview blog home page from another pages, not to app homepage.
I use these code:
In fragmentblog.java
public class FragmentBlog extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_blog, container, false);
WebView webView=(WebView)rootView.findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setBuiltInZoomControls(false);
webView.getSettings().setSupportZoom(true);
webView.setWebViewClient(new WebViewClient());
webView.loadUrl("https://google.com");
return rootView;
}
}
In fragment_blog.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/webView" />
</RelativeLayout>
</LinearLayout>
Please help me to do this. Advance Thanks!!!

How to work with preference in single activity design using navigation component?

I want to migrate to single activity design using navigation component. I am using one activity and others are fragment. For some screens, I have only layouts, no preference. No problems to inflate those in fragment. But i faced problem when i try to work with preference.
My requirements is:
I need to inflate a toolbar and preference list in a fragment.
My approaches:
Add preference using this following code.
SettingFragment.java
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.setting_main, rootKey);
}
Configure for app bar for navigation component.
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mNavController = Navigation.findNavController(view);
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(mNavController.getGraph()).build();
Toolbar toolbar = view.findViewById(R.id.the_toolbar);
NavigationUI.setupWithNavController(toolbar, mNavController, appBarConfiguration);
}
In app theme, i used a layout for preference which contains toolbar and framelayout.
<style name="Theme.MyApp" parent="#style/Theme.AppCompat.Light.NoActionBar">
...
<item name="preferenceTheme">#style/PreferenceThemeOverlay</item>
</style>
<style name="PreferenceThemeOverlay">
<item name="android:layout">#layout/fragment_settings </item>
</style>
fragment_settings.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="#+id/the_toolbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:layout_gravity="bottom"
android:layout_marginBottom="12dp"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#android:id/list_container">
</FrameLayout>
</LinearLayout>
setting_main.xml
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="MyApp"
android:title="My application">
<androidx.preference.Preference
android:icon="#drawable/ic_list1"
android:key="PreferenceList1"
android:title="PreferenceList1" />
<androidx.preference.PreferenceCategory android:key="SecondCategory">
<androidx.preference.Preference
android:icon="#drawable/ic_list2"
android:key="PreferenceList2"
android:title="PreferenceList2" />
</androidx.preference.PreferenceCategory>
</androidx.preference.PreferenceScreen>
My problems:
If I do this, I can successfully add toolbar and preference. But i see a blinking issue in title during transaction from one fragment to another.
I have searched a lot, but did not find any suitable solutions. I am a newbie.
My questions:
How can I solve this issue?
Is there any way to work with preference in navigation component which also have a toolbar and preference in Fragment?
For others fragment, which does not have preference i can inflate using this code which works fine with no blink issue. Is there any ways to do this for preference also adjusting with my requirements?
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable
Bundle savedInstanceState) {
return inflater.inflate(R.layout.setting_main_fragment, container, false);
}

How to provide navigation for an app that supports tablets and handsets

I know this might been asked before but since I didn't find anything convincing, I need to ask again.
How do you design an app that's going to support tablets and handsets when you also need to provide some sort navigation panel(e.g. Navigation Drawer)?
I think I know how to use the Navigation Drawer with handsets and tablets in portrait orientation because in those cases I'm only showing a single pane(fragment) at the time. But with tablets in landscape that's totally different since you have enough room to display at least two panes(fragments) that most of the time are going to be related in a sort of "mater-detail" way.
Edit #1
Just to provide a bit of context about my app and why I think I need to have two panes apart from the navigation list.
Well the main goal of my app is to help waiters take orders, this scenario comes into play when:
The waiter selects the option "Take order" from the left menu (ideally a navigation drawer)
In the first part(left pane) of the the what I called the "Content Part", the waiter can choose among all the categories of food they serve (pretend it's the list at the top) and according to the category selected, the below list shows all the dishes under that specific category.
Once the waiter taps on a dish it's automatically added to the second part(right pane) of the "Content Part"
Knowing that the basic structure of a navigation drawer is similar to this:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The main content view -->
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<ListView android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:background="#111"/>
</android.support.v4.widget.DrawerLayout>
How do you handle the "tablet-in-landscape-orientation" scenario? Do you use nested fragments for the multi-pane layout that might be necessary to use in this case?(that sounds awfully complicated) Do you use a custom library perhaps? Do you know of any open source app in Git that implements this and that I can use as a reference?
EDIT #2
After trying some ideas, I realized that the most convenient way of implementing the same navigation drawer for multiple activities, was to create a BaseActivity that would handle all the drawer functionality and from which all my activities could inherit.
This is what I've got so far:
BaseActivity
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
public class BaseActivity extends Activity {
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
private ListView mDrawerListView;
protected void onCreate(Bundle savedInstanceState, int resLayoutID) {
setContentView(resLayoutID);
super.onCreate(savedInstanceState);
setupNavDrawer();
}
private void setupNavDrawer() {
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerListView = (ListView) findViewById(R.id.drawer);
mDrawerListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
String[] rows = getResources().getStringArray(R.array.drawer_rows);
mDrawerListView.setAdapter(new ArrayAdapter<String>(
this, R.layout.drawer_row, rows));
mDrawerToggle =
new ActionBarDrawerToggle(this, mDrawerLayout,
R.string.drawer_open,
R.string.drawer_close);
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listView, View row,
int position, long id) {
if (position == 0) {
Log.d("Menu", "European Union");
} else {
Log.d("Menu", "Other Option");
}
mDrawerLayout.closeDrawers();
}
});
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Every activity that needs to have a Navigation Drawer now needs to extend the BaseActivity:
EuropeanUnionActivity
public class EuropeanUnionActivity extends BaseActivity{
//...
}
Also every activity layout needs to contain in its code a android.support.v4.widget.DrawerLayout element like this:
activity_europeanunion
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="#layout/main" />
<ListView
android:id="#+id/drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:background="#111"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp" />
</android.support.v4.widget.DrawerLayout>
Here's important to mention that the ID's for the DrawerLayout(drawer_layout) and the ListView(drawer) needs to be the same in all the activity layouts that are going to have a navigation drawer because those ID's are used by the BaseActivity.
For the sake of brevity and to quickly test this approach I have used this example by #CommonsWare (I hope he doesn't mind). There you can find the implementation for #layout/main.
Now, although almost everything works as expected, I haven't been able to understand why if I take the code for the ListView and place it in a separate file listview_options the Navigation drawer simply wouldn't close and tapping on the ActionBarDrawerToggle would only make the app crash and show this in the LogCat:
FATAL EXCEPTION: main
Process: com.idealsolution.simplenavigationdrawer, PID: 17725
java.lang.IllegalArgumentException: No drawer view found with gravity LEFT
at android.support.v4.widget.DrawerLayout.openDrawer(DrawerLayout.java:1293)
at android.support.v7.app.ActionBarDrawerToggle.toggle(ActionBarDrawerToggle.java:290)
at android.support.v7.app.ActionBarDrawerToggle.onOptionsItemSelected(ActionBarDrawerToggle.java:280)
at com.idealsolution.simplenavigationdrawer.BaseActivity.onOptionsItemSelected(BaseActivity.java:86)
at android.app.Activity.onMenuItemSelected(Activity.java:2608)
at com.android.internal.widget.ActionBarView$3.onClick(ActionBarView.java:167)
at android.view.View.performClick(View.java:4456)
at android.view.View$PerformClick.run(View.java:18465)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5086)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
This is line 86:
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item)) { //Line 86
return true;
}
return super.onOptionsItemSelected(item);
}
This is the same code for
activity_europeanunion, but using a include tag for the ListView
<include layout="#layout/main" />
<include layout="#layout/listview_options" />
The code for listview_options.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/menu_layout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="#+id/drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:background="#111"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp" />
</LinearLayout>
This is the code I tried in the BaseActivity to retrieve the ListView, but that obviously isn't working:
private void setupNavDrawer() {
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
//Please pay special attention to the following two lines
mDrawerLinearLayout = (LinearLayout) findViewById(R.id.menu_layout);
mDrawerListView = (ListView) mDrawerLinearLayout.findViewById(R.id.drawer);
mDrawerListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
String[] rows = getResources().getStringArray(R.array.drawer_rows);
mDrawerListView.setAdapter(new ArrayAdapter<String>(
this, R.layout.drawer_row, rows));
mDrawerToggle =
new ActionBarDrawerToggle(this, mDrawerLayout,
R.string.drawer_open,
R.string.drawer_close);
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listView, View row,
int position, long id) {
//...
mDrawerLayout.closeDrawers();
}
});
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
}
Any ideas and suggestions are welcome.
Thanks.
P.S. I found this question in which it is said that using a Navigation Drawer is not advisable.
For phone and tablet-portrait mode you can use a layout like this:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<include layout="#layout/fragments_layout" />
<include layout="#layout/drawer_list" />
</android.support.v4.widget.DrawerLayout>
This could be the layout for the tablet-landscape mode:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<include layout="#layout/drawer_list" />
<include layout="#layout/fragments_layout" />
</LinearLayout>
Here is drawer_list:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="260dp"
android:layout_height="match_parent"
android:layout_gravity="start" >
<ListView
android:id="#+id/drawer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:choiceMode="singleChoice"
android:background="#111"
android:divider="#android:color/darker_gray"
android:dividerHeight="0dp" />
</RelativeLayout>
and fragments_layout:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment android:id="+#id/master_fragment" />
<fragment android:id="+#id/detail_fragment" />
</FrameLayout>
On the activity, you'll have to check if you're in tablet-landscape mode and show both fragments. Otherwise, you'll show master fragment first, hiding the details
If navigation drawer is visible on all activities, declare an abstract activity that takes care of the drawer. Then, all the activities inherit from this abstract activity. The BaseActivity you posted is a good example

Implementing Action Bar Tabs for an Activity creating a MapFragment

this is a similar question to: MapFragment in Action Bar Tabs but there wasn't a clear answer from this that I understood. I am new to Android and this is my first application Im developing .
I currently have one MainActivity that creates a MapFragment for Google Maps v2. and displays a map under an ActionBar as shown in this screenshot
My objective is to implement tabs (Not using FragmentActivitys or the support Library as my application is minSdkVersion=11) for the MainActivity in Eclipse which currently creates a MapFragment for Google Maps v2.
MainActivity.java snippet
public class MainActivityextends Activity
implements LocationListener, LocationSource, OnMarkerClickListener, OnInfoWindowClickListener {
private static GoogleMap googleMap;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); //Change to Tab mode
....
googleMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
map.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<include
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
layout="#layout/map_fragment" />
</LinearLayout>
map_fragment.xml
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="#+id/map"
android:name="com.google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:cameraTargetLat="53.78513542767"
map:cameraTargetLng="-3.14948167651"
map:cameraZoom="14" />
Eclipse sets up tabs for you with an Activity using the support library so it gave me an error(below) when using a MapFragment and I reverted back to not using tabs. Reason for this I think is here
Caused by: java.lang.ClassCastException: com.google.android.gms.maps.MapFragment cannot be cast to android.support.v4.app.Fragment
I need to use tabs as currently only one page/activity has been developed and I need a way to display filters to the user as well as the map. The user will switch to the adjacent tab to edit filters and be able to switch back to the Map tab where the filters will then be picked up and alter the markers on the map.
So short question is there a simple way for me to implement tabs for my MainActivity.java? If this isnt clear just ask me specifics but this is very advanced for me
try using SupportMapFragment instead of MapFragment:
map.xml
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:cameraTargetLat="53.78513542767"
map:cameraTargetLng="-3.14948167651"
map:cameraZoom="14" />

Android activity crashes when I try to use an AlertDialog and a custom Dialog

I'm writing my first Android application and I have one activity that I'd like to display two separate dialogs:
Dialog A - A simple AlertDialog that shows text and gets dismissed
Dialog B - A "Save As" pop-up with an EditText and Save and Cancel buttons
I've found tutorials on creating AlertDialogs and Custom Dialogs and I've been able to get each of them to work, but only separately. When I try to put all of the code into a switch/case statement in the onCreateDialog method, the application crashes when the AlertDialog is launched.
Here's my onCreateDialog code:
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
// Display dialog
case 0:
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
alertDialog.setMessage(messageText);
alertDialog.setNegativeButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
return alertDialog.create();
// Save As dialog
case 1:
Dialog dialog = new Dialog(this);
dialog.setContentView(R.layout.save_as);
dialog.setTitle("Save as:");
Button cancel = (Button)findViewById(R.id.cancel);
cancel.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
}
});
return dialog;
}
return null;
}
Either case will work by itself, but the application crashes when I put both cases in.
Here's the XML for the custom dialog layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:text="Save this list as:"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<EditText
android:id="#+id/list_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#android:drawable/bottom_bar"
android:paddingLeft="4.0dip"
android:paddingTop="5.0dip"
android:paddingRight="4.0dip"
android:paddingBottom="1.0dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button
android:id="#+id/save"
android:layout_width="0.0dip"
android:layout_height="fill_parent"
android:text="Save"
android:layout_weight="1.0"
></Button>
<Button
android:id="#+id/cancel"
android:layout_width="0.0dip"
android:layout_height="fill_parent"
android:text="Cancel"
android:layout_weight="1.0"
></Button>
</LinearLayout>
</LinearLayout>
Should I stick with just one format or the other? I've also read that DialogFragments are preferred now, but I haven't found any good novice-level tutorials on those yet. Any suggestions will be greatly appreciated.
I eventually realized that I needed to pass data to and from the dialog, and I am targeting a low API so I just changed the Save As dialog to an Activity, and everything works fine. Learned a lot of limitations of dialogs along the way though....

Resources