Android - keep variable's value in main activity - android

I'd like to know if there's any solution to keep variables value in memory when I go to another activity and then back to main activity (main activity wasn't killed - onCreate(Bundle) parameter is null). In my case variable is ArrayList.
I've solved this problem by declaring variable as static. This solution is based on this answer: https://stackoverflow.com/a/14604485/3195752.
It works, but I don't like it. Each instance of class should have own variable (list). I know I'll have only one instance of activity but still it's doesn't seem right.
Thank you for your answers!
EDIT #1
Adding some code for atxe
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.nuduoz.batchelorwork.uiprototype2" >
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:logo="#drawable/ic_action_floorplan_icon_green"
android:theme="#style/Theme.Lightgreen" >
<activity
android:name="com.nuduoz.batchelorwork.uiprototype2.RoomArrange"
android:label="#string/activity_room_arrange"
android:theme="#style/Theme.Lightgreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.nuduoz.batchelorwork.uiprototype2.FloorPlan"
android:label="#string/title_activity_floor_plan"
android:parentActivityName="com.nuduoz.batchelorwork.uiprototype2.RoomArrange"
android:theme="#style/Theme.Lightgreen">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="RoomArrange" />
</activity>
</application>
activity_room_arrange.xml
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="MergeRootFrame">
<!-- The main content view -->
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.nuduoz.batchelorwork.uiprototype2.RoomArrange"
android:background="#android:color/white"
/>
<!-- The left floor plan drawer -->
<ListView android:id="#+id/left_drawer"
android:layout_width="#dimen/left_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#color/d_green"
android:dividerHeight="1dp"
android:background="#color/action_bar_color"/>
<!-- The right add equipment drawer -->
<LinearLayout android:id="#+id/right_drawer"
android:orientation="vertical"
android:layout_width="#dimen/right_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="end"
android:choiceMode="singleChoice"
android:divider="#color/d_green"
android:dividerHeight="1dp"
android:background="#color/action_bar_color"/>
</android.support.v4.widget.DrawerLayout>
RoomArrange.java - I tried to delete all lines that doesn't affect activity change
public class RoomArrange extends ActionBarActivity {
public final static String PLAN_NAME_MESSAGE = "com.nuduoz.batchelorwork.uiprototype2.PLAN_NAME_MESSAGE";
private final static String PLAN_LIST_BUNDLE_ID = "com.nuduoz.batchelorwork.uiprototype2.PLAN_LIST_BUNDLE_ID";
private static ArrayList<String> mFloorPlanList = new ArrayList<String>();
private DrawerLayout mLeftDrawerLayout;
private DrawerLayout mRightDrawerLayout;
private ListView mLeftDrawerList;
private LinearLayout mRightDrawerItems;
private CharSequence mTitle;
private ActionBarDrawerToggle mLeftDrawerToggle;
private ActionBarDrawerToggle mRightDrawerToggle;
private CharSequence mDrawerTitle;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_room_arrange);
mTitle = mDrawerTitle = getTitle();
// Fill list when its empty - application start
if(mFloorPlanList.size() == 0)
{
List<String> tmpList = Arrays.asList(getResources().getStringArray(R.array.floorplans_array));
mFloorPlanList.addAll(tmpList);
mFloorPlanList.add(getResources().getString(R.string.drawer_add_new_plan));
}
mLeftDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mLeftDrawerList = (ListView) findViewById(R.id.left_drawer);
mRightDrawerItems = (LinearLayout) findViewById(R.id.right_drawer);
// set up the drawer's list view with items and click listener
mLeftDrawerList.setAdapter(new ArrayAdapter<String>(this,
R.layout.drawer_list_item, mFloorPlanList));
if (savedInstanceState == null)
{
//selectItem(0);
}
else
{
mFloorPlanList = savedInstanceState.getStringArrayList(PLAN_LIST_BUNDLE_ID);
mLeftDrawerList.setAdapter(new ArrayAdapter<String>(this,
R.layout.drawer_list_item, mFloorPlanList));
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mLeftDrawerToggle.onOptionsItemSelected(item))
{
closeRightDrawer();
return true;
}
switch (item.getItemId()) {
// action with ID action_refresh was selected
case R.id.action_arrange_add:
onAddActionSelected();
return true;
//......
default:
break;
}
return super.onOptionsItemSelected(item);
}
// Click for swapping floor plans
private class DrawerItemClickListener implements ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
selectItem(position);
}
}
#Override
public void onSaveInstanceState(Bundle bundle)
{
bundle.putStringArrayList(PLAN_LIST_BUNDLE_ID, mFloorPlanList);
bundle.putInt("a", 25);
super.onSaveInstanceState(bundle);
}
/** Swaps floor plans, create new or edit */
private void selectItem(int position) {
// Create new floor plan
if(position == mFloorPlanList.size() - 1)
{
// TODO Create new floor plan
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle(getResources().getString(R.string.drawer_add_new_plan));
alert.setMessage("Add name of a plan");
// Set an EditText view to get user input
final EditText input = new EditText(this);
alert.setView(input);
final RoomArrange activity = this;
alert.setPositiveButton(getResources().getString(R.string.button_ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String value = input.getText().toString();
mFloorPlanList.add(mFloorPlanList.size() - 1, value);
// Call floor plan activity
Intent intent = new Intent(activity, FloorPlan.class);
intent.putExtra(PLAN_NAME_MESSAGE, value);
startActivity(intent);
}
});
alert.setNegativeButton(getResources().getString(R.string.button_cancel), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// Canceled.
}
});
alert.show();
}
}
}
activity_floor_plan.xml
<RelativeLayout 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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="com.nuduoz.batchelorwork.uiprototype2.FloorPlan">
<TextView
android:text="#string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
FloorPlan.java
public class FloorPlan extends ActionBarActivity {
public final static String PLAN_NAME = "New floor plan";
private String planName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_floor_plan);
Bundle extras;
if (savedInstanceState == null) {
extras = getIntent().getExtras();
if(extras == null) {
planName= getResources().getString(R.string.plan_default_name);
} else {
planName= extras.getString(RoomArrange.PLAN_NAME_MESSAGE);
}
} else {
planName= (String) savedInstanceState.getSerializable(RoomArrange.PLAN_NAME_MESSAGE);
}
getActionBar().setTitle(planName);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.floor_plan, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
I really don't know where problem is.. :(
ad: I know I could have some problems in my code so feel free to point out them.

If you declare the variable as static you do not have the warranty that the variable value will remain there on resuming that activity. The OS might kill your activity if running out of memory.
As commented in another answer, saving that information into a data store (file system, shared preferences, sqlite,...) is an option. But, in my opinion is not the most clean way. I prefer to recreate the activity (and its state) as Android documentation suggests: using onSaveInstanceState() to store the data you want on the recreation and then retrieving it in onCreate() (from the bundle) or onRestoreInstanceState().
Check the documentation here: http://developer.android.com/training/basics/activity-lifecycle/recreating.html

Use internal data to store the data. See here for more info: http://developer.android.com/guide/topics/data/data-storage.html#filesInternal
This works relatively well, and is persistent through restarts, but it is a pain to read and write.

Related

Android: How to make a Button Lead to a ListView item details (In differents Activities) (Master / Detail Flow)

I am a beginner in Android development.
I know, that title seems difficult to understand, but please let me explain
My app is a Bus Lines Guide of my city, it contains two distinct Views:
A ListView with all bus lines in numerical, simple order, nothing
special. It contains exactly 100 items.
A NavigationDrawer IN ANOTHER ACTIVITY with these same lines, but separated by zones (North, South, East, Southeast)
Each NavigationDrawer menu leads to an Activity with several buttons and bus lines, but only those belonging to Zone X (East, for example)
Here the layout of ActivityEast:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="6dp"
android:paddingBottom="6dp"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/activity_leste" tools:context="com.lennoardsilva.teresinabus.Leste">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/scrollView2"
android:layout_alignParentTop="true">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/l_245"
android:id="#+id/botao_l_245" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/l_401"
android:id="#+id/botao_l_401" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/l_402"
android:id="#+id/botao_l_402" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/l_403"
android:id="#+id/botao_l_403" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/l_404"
android:id="#+id/botao_l_404" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/l_405"
android:id="#+id/botao_l_405" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/l_501"
android:id="#+id/botao_l_501" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/l_502"
android:id="#+id/botao_l_502" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/l_503"
android:id="#+id/botao_l_503" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/l_512"
android:id="#+id/botao_l_512" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/l_513"
android:id="#+id/botao_l_513" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/l_518"
android:id="#+id/botao_l_518" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/l_520"
android:id="#+id/botao_l_520" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/l_521"
android:id="#+id/botao_l_521" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/l_522"
android:id="#+id/botao_l_522" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/l_523"
android:id="#+id/botao_l_523" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/l_610"
android:id="#+id/botao_l_610" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/carregar_mais"
android:id="#+id/botao_carregar_leste"
android:background="#color/cinza_escuro"
android:textColor="#color/branco"
android:textStyle="bold"
android:onClick="leste_2"
android:visibility="gone" />
</LinearLayout>
</ScrollView>
</RelativeLayout>
<!-- As a told you, a lot of buttons -->
Here LineListFragment:
package com.lennoardsilva.teresinabus;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.lennoardsilva.teresinabus.dummy.DummyContent;
public class LinhaListFragment extends ListFragment {
private static final String STATE_ACTIVATED_POSITION = "activated_position";
private Callbacks mCallbacks = sDummyCallbacks;
private int mActivatedPosition = ListView.INVALID_POSITION;
public interface Callbacks {
public void onItemSelected(String id);
}
private static Callbacks sDummyCallbacks = new Callbacks() {
#Override
public void onItemSelected(String id) {
}
};
public LinhaListFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new ArrayAdapter<DummyContent.DummyItem>(getActivity(),android.R.layout.simple_list_item_activated_1, android.R.id.text1, DummyContent.ITEMS));
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (savedInstanceState != null && savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION));
}
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Activities containing this fragment must implement its callbacks.
if (!(activity instanceof Callbacks)) {
throw new IllegalStateException("Activity must implement fragment's callbacks.");
}
mCallbacks = (Callbacks) activity;
}
#Override
public void onDetach() {
super.onDetach();
mCallbacks = sDummyCallbacks;
}
#Override
public void onListItemClick(ListView listView, View view, int position, long id) {
super.onListItemClick(listView, view, position, id);
mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mActivatedPosition != ListView.INVALID_POSITION) {
outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
}
}
public void setActivateOnItemClick(boolean activateOnItemClick) {
getListView().setChoiceMode(activateOnItemClick ? ListView.CHOICE_MODE_SINGLE : ListView.CHOICE_MODE_NONE);
}
private void setActivatedPosition(int position) {
if (position == ListView.INVALID_POSITION) {
getListView().setItemChecked(mActivatedPosition, false);
} else {
getListView().setItemChecked(position, true);
}
mActivatedPosition = position;
}
}
Here the Line ListActivity:
public class LinhaListActivity extends AppCompatActivity
implements LinhaListFragment.Callbacks {
private boolean mTwoPane;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_linha_app_bar);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setTitle(getTitle());
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
DialogFragment dialog = new FragmentoDatabase();
dialog.show(getFragmentManager(), "FragmentoDatabaseTag");
}
});
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
if (findViewById(R.id.linha_detail_container) != null) {
mTwoPane = true;
((LinhaListFragment) getSupportFragmentManager()
.findFragmentById(R.id.linha_list))
.setActivateOnItemClick(true);
}
// TODO: If exposing deep links into your app, handle intents here.
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onItemSelected(String id) {
if (mTwoPane) {
Bundle arguments = new Bundle();
arguments.putString(LinhaDetailFragment.ARG_ITEM_ID, id);
LinhaDetailFragment fragment = new LinhaDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction().replace(R.id.linha_detail_container, fragment).commit();
} else {
Intent detailIntent = new Intent(this, LinhaDetailActivity.class);
detailIntent.putExtra(LinhaDetailFragment.ARG_ITEM_ID, id);
startActivity(detailIntent);
}
}
}
Here DummyContent:
public class DummyContent {
public static List<DummyItem> ITEMS = new ArrayList<DummyItem>();
public static Map<String, DummyItem> ITEM_MAP = new HashMap<String, DummyItem>();
static {
addItem(new DummyItem("1", "004 - LINE NAME", "Line 004 Details"));
addItem(new DummyItem("2", "005 - LINE NAME", "Line 005 Details"));
addItem(new DummyItem("3", "And so on....", "Details"));
addItem(new DummyItem("100", "100 - LINE NAME", "Line 100 Details"));
}
private static void addItem(DummyItem item) {
ITEMS.add(item);
ITEM_MAP.put(item.id, item);
}
public static class DummyItem {
public String id;
public String content;
public String details;
public DummyItem(String id, String content, String details) {
this.id = id;
this.content = content;
this.details = details;
}
#Override
public String toString() {
return content;
}
}
}
Question: How to make one of these buttons start the corresponding ItemDetailsActivity the ListView?
Example: In ActivityEast I have the botao_l_501, in ListView it corresponds to item 33.
I want botao_l_501 start the details of item 33 of the ListView. (Template Master / Detail Flow, Google)
Things you might want to know:
The ListView is in another Activity, separated from all the items in
the Navigation Drawer, but you can start it by a FAB;
The ListView is a model of the Master / Detail Flow. The items are
already set (Its details not yet);
So basically you need to share the adapter's information that is in LinhaListFragment with the zones activities (i.e. ActivityEast). The problem is that in LinhaListFragment you've an Adapter because you're using a ListFragment but in the ActivityEast you've a LinearLayout with a bunch of Buttons, so how we do map those two things to work together?
First solution (Hack & Nasty)
In your DummyContent class that when you're adding the items, add also a reference to the Button id:
static {
addItem(new DummyItem(R.id.idbotao_l_001, "1", "004 - LINE NAME", "Line 004 Details"));
addItem(new DummyItem(R.id.idbotao_l_002, "2", "005 - LINE NAME", "Line 005 Details"));
addItem(new DummyItem(R.id.idbotao_l_033, "33", "033 - LINE NAME", "Details"));
addItem(new DummyItem(R.id.idbotao_l_100, "100", "100 - LINE NAME", "Line 100 Details"));
}
Then in the onClick of each button you can do something like:
#Override
public void onClick(View view) {
for (DummyItem item : DummyContents.ITEMS) {
if (item.resourceId == view.getId()) {
//Start the item detail activity
break;
}
}
}
I don't know if you're using a DummyContent class because your content is never going to change of if you're using It because you're just testing the code. If in the future you're going to fetch that data from a webservice then this solution is useless.
Second solution (Clean)
First of all if you really want to follow the master/detail specs then you should use activities only as fragment holders, therefore the zones activities like ActivityEast shouldn't exist neither you should've a LinearLayout with a bunch of buttons. Replace it by a ZoneActivity which contains a ZoneFragment with a RecyclerView (nobody uses ListView or ListFragment anymore) the RecyclerView should be set with the same Adapter that you use in the LinhaListFragment when you start a ZoneActivity It's a requirment that the zone id is send by the bundle of the Intent that id is pass through the ZoneFragment and finally set to the Adapter. The Adapter contains the logic to filter/show the lines per zone. The zone id parameter shouldn't be necessary because the ListFragment It's also going to use the same adapter and doesn't has a zone id.
Since you said that you just started in android development there's some tips that'd help you:
Don't use ListView use RecyclerView instead.
Never do something like you did in ActivityEast if you're going to have so many buttons use a RecyclerView even if your data is static.
Nobody uses things like ListFragment any more. If you extends from something like that you're attach to that class, try to inherith from your own base classes or the very basic base classes like Fragment and Activity.
Try to use regions no separate your code. For example:
public class MyFragment extends Fragment {
//region Variables
private int myField;
//endregion
//region Fragment lifecycle
protected void onCreate(Bundle saveInstance) {
//...
}
//endregion
}
You can then fold them and read the code in a more confortable way.
Never start an activity explicity for example:
BAD
Intent intent = new Intent(context, MyActivity.class);
intent.putExtra("zoneId",myZoneId);
startActivity(intent);
GOOD
startActivity(MyActivity.getStartIntent(context, myZoneId));
....
//In MyActivity class
public static getStartIntent(Context context, int zoneId) {
Intent intent = new Intent(context, MyActivity.class);
intent.putExtra(MyActiviy.ZONE_ID, zoneId);
return zoneId;
}
}

android nested fragment doesn't work properly

I'm trying to show a nested fragment inside my fragment on button click, so on button .setOnClickListener (which works fine with Log.d) of my main fragment i've placed:
Fragment noteFragment = new FrontPageNote();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.frontNote, noteFragment).commit();
as found on developer guide, where FrontPageNote is my nested fragment (which obviously extends Fragment) and R.id.frontNote is the id of the xml layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingBottom="48dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp"
android:layout_weight="1"
android:id="#+id/frontNote"
android:background="#color/Background">
<LinearLayout
android:id="#+id/linearLayoutFront"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="5dp"
android:paddingTop="15dp">
<EditText
android:id="#+id/titleEditFront"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="#string/titleEdit"
android:textColor="#color/TextColor.White"/>
<EditText
android:id="#+id/noteEditFront"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="#string/noteEdit"
android:paddingTop="20dp"
android:textColor="#color/TextColor.White"
android:inputType="textMultiLine" />
</LinearLayout>
</RelativeLayout>
the nested fragment FrontPageNote also is linked to this xml using getActivity().setContentView(R.layout.front_note); under onCreate() method.
Q. what am I doing wrong? thanks
EDIT: added FrontPageNote.class:
public class FrontPageNote extends Fragment {
// Declare Variables
public static long rowID;
private EditText title_edit;
private EditText note_edit;
private static final String TITLE = "title";
private static final String NOTE = "note";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
getActivity().setContentView(R.layout.front_note);
// Locate the EditText in add_note.xml
title_edit = (EditText) getActivity().findViewById(R.id.titleEditFront);
note_edit = (EditText) getActivity().findViewById(R.id.noteEditFront);
// Retrieve the Row ID from ViewNote.java
Bundle extras = getActivity().getIntent().getExtras();
if (extras != null) {
rowID = extras.getLong("row_id");
title_edit.setText(extras.getString(TITLE));
note_edit.setText(extras.getString(NOTE));
}
}
// Create an ActionBar menu
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_all_geofences, menu);
menu.add("Save changes")
.setOnMenuItemClickListener(this.SaveButtonClickListener)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
super.onCreateOptionsMenu(menu, inflater);
}
// Capture save menu item click
OnMenuItemClickListener SaveButtonClickListener = new OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
// Passes the data into saveNote() function
if (title_edit.getText().length() != 0) {
AsyncTask<Object, Object, Object> saveNoteAsyncTask = new AsyncTask<Object, Object, Object>() {
#Override
protected Object doInBackground(Object... params) {
saveNote();
return null;
}
#Override
protected void onPostExecute(Object result) {
// Close this activity
//getActivity().finish();
}
};
// Execute the saveNoteAsyncTask AsyncTask above
saveNoteAsyncTask.execute((Object[]) null);
}
else {
// Display a simple alert dialog that forces user to put in a title
AlertDialog.Builder alert = new AlertDialog.Builder(
getActivity());
alert.setTitle("Title is required");
alert.setMessage("Put in a title for this note");
alert.setPositiveButton("Okay", null);
alert.show();
}
return false;
}
};
// saveNote() function
private void saveNote() {
DatabaseConnector dbConnector = new DatabaseConnector(getActivity());
if (getActivity().getIntent().getExtras() == null) {
// Passes the data to InsertNote in DatabaseConnector.java
dbConnector.InsertNote(title_edit.getText().toString(), note_edit
.getText().toString());
} else {
// Passes the Row ID and data to UpdateNote in DatabaseConnector.java
dbConnector.UpdateNote(rowID, title_edit.getText().toString(),
note_edit.getText().toString());
}
}
}

widget.FrameLayout$LayoutParams cannot be cast to android.support.v4.widget.DrawerLayout$LayoutParams

I'm having a few issues with my NavigationDrawerwhich I want to run from and Activitywhich contains 2 fragments. The idea is that the main fragment will be changed by selecting from the NavigationDrawer
I'm getting the following error when running:
Process: XXXX, PID: 31040
java.lang.ClassCastException: android.widget.FrameLayout$LayoutParams cannot be cast to android.support.v4.widget.DrawerLayout$LayoutParams
at android.support.v4.widget.DrawerLayout.isDrawerView(DrawerLayout.java:1129)
at android.support.v4.widget.DrawerLayout.isDrawerOpen(DrawerLayout.java:1379)
at XXXX.NavigationDrawerFragment.isDrawerOpen(NavigationDrawerFragment.java:117)
at XXXX.EditFactFind.onCreateOptionsMenu(EditFactFind.java:192)
at android.app.Activity.onCreatePanelMenu(Activity.java:2846)
at com.android.internal.policy.PhoneWindow.preparePanel(PhoneWindow.java:567)
at com.android.internal.policy.PhoneWindow.doInvalidatePanelMenu(PhoneWindow.java:939)
at com.android.internal.policy.PhoneWindow$1.run(PhoneWindow.java:271)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
My activity that contains the fragments XML is:
<?xml version="1.0" encoding="utf-8"?>
<!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. -->
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="XXXX.MainActivity">
<!-- As the main content view, the view below consumes the entire
space available using match_parent in both dimensions. -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="250dp"
android:id="#+id/fragment_container"
android:layout_alignParentBottom="true">
<!-- android:layout_gravity="start" tells DrawerLayout to treat
this as a sliding drawer on the left side for left-to-right
languages and on the right side for right-to-left languages.
If you're not building against API 17 or higher, use
android:layout_gravity="left" instead. -->
<!-- The drawer is given a fixed width in dp and extends the full height of
the container. -->
<fragment
android:id="#+id/navigation_drawer"
android:layout_width="#dimen/navigation_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
android:name="XXXX.NavigationDrawerFragment"
tools:layout="#layout/fragment_navigation_drawer" />
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:id="#+id/editFactFindTop"
android:name="XXXX.editFactFind_top"
tools:layout="#layout/fragment_edit_fact_find_top"/>
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="3"
android:id="#+id/fragment_editFactFind"
android:name="XXXX.secA_pg1"
tools:layout="#layout/fragment_sec_a_pg1" />
</FrameLayout>
</android.support.v4.widget.DrawerLayout>
My NavigationDrawer XML is:
<ListView 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:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:background="#cccc"
tools:context=".NavigationDrawerFragment" />
My Top fragment XML is:
<android.support.v4.widget.DrawerLayout 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"
tools:context="XXXX.editFactFind_top">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="250dp"
android:id="#+id/fragment_container"
android:layout_alignParentBottom="true">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="#string/titleEditText"
android:id="#+id/titleViewText" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/titleViewText"
android:layout_alignBaseline="#id/titleViewText"
android:id="#+id/titleEditText"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/titleEditText"
android:layout_alignBaseline="#id/titleViewText"
android:layout_alignParentRight="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_marginLeft="20dp"
android:text="#string/dateTextView"
android:id="#id/dateTextView"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/saveButton"
android:id="#id/saveButton"
android:layout_below="#id/titleEditText"
android:layout_marginTop="50dp"
android:visibility="visible" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/cancelButton"
android:layout_marginLeft="10dp"
android:id="#id/cancelButton"
android:layout_toRightOf="#id/saveButton"
android:layout_alignBaseline="#id/saveButton"
android:visibility="visible" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Next"
android:id="#+id/nextButton"
android:layout_alignBaseline="#id/cancelButton"
android:layout_toRightOf="#id/cancelButton"/>
</RelativeLayout>
</FrameLayout>
</android.support.v4.widget.DrawerLayout>
My main fragment XML is:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="XXXX.secA_pg1">
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:layout_width="match_parent" android:layout_height="match_parent"
android:text="#string/Sec_A_pg1_fragment"
android:id="#+id/Sec_A_pg1_fragment"
android:layout_below="#id/nextButton"/>
</RelativeLayout>
</FrameLayout>
</android.support.v4.widget.DrawerLayout>
My editFactFind java is:
public class EditFactFind extends Activity implements NavigationDrawerFragment.NavigationDrawerCallbacks {
public static final int RESULT_DELETE = -500;
private boolean isInEditMode = true;
private boolean isAddingFactFind = true;
private NavigationDrawerFragment mNavigationDrawerFragment;
private CharSequence mTitle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_factfind);
final Button saveButton = (Button)findViewById(R.id.saveButton);
final Button cancelButton = (Button)findViewById(R.id.cancelButton);
final EditText titleEditText = (EditText)findViewById(R.id.titleEditText);
//final EditText factFindEditText = (EditText)findViewById(R.id.factFindEditText);
final TextView dateTextView = (TextView)findViewById(R.id.dateTextView);
final Button nextButton =(Button) findViewById(R.id.nextButton);
//Create fragment and give it an argument for the selected article
secA_pg1 iniSecFrag = new secA_pg1();
Bundle args = new Bundle();
args.putInt(secA_pg1.ARG_INDEX, 1);
iniSecFrag.setArguments(args);
FragmentTransaction initialTransaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
//initialTransaction.replace(R.id.fragment_container, iniSecFrag);
// initialTransaction.addToBackStack(null);
// Fragment iniSecFrag = new secA_pg1();
initialTransaction.add(R.id.fragment_container, iniSecFrag);
//Commit the transaction
initialTransaction.commit();
mNavigationDrawerFragment = (NavigationDrawerFragment)
getFragmentManager().findFragmentById(R.id.navigation_drawer); // Activity_nav_drawer.xml
mTitle = getTitle();
// Set up the drawer.
mNavigationDrawerFragment.setUp(
R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout));
Serializable extra = getIntent().getSerializableExtra("FactFind");
if(extra != null)
{
FactFind factFind = (FactFind) extra;
titleEditText.setText(factFind.getTitle());
// factFindEditText.setText(factFind.getFactFindTitle());
DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
String date = dateFormat.format(factFind.getDate());
dateTextView.setText(date);
isInEditMode = false;
titleEditText.setEnabled(false);
// factFindEditText.setEnabled(false);
saveButton.setText("Edit");
isAddingFactFind = false;
}
cancelButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
setResult(RESULT_CANCELED, new Intent());
finish();
}
});
nextButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//secA_pg1 secFrag = (secA_pg1) getFragmentManager().findFragmentById(R.id.Sec_A_pg1_fragment);
//Create fragment and give it an argument for the selected article
secA_pg2 newSecFrag = new secA_pg2();
Bundle args = new Bundle();
args.putInt(secA_pg2.ARG_INDEX, 2);
newSecFrag.setArguments(args);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
transaction.replace(R.id.fragment_editFactFind, newSecFrag);
transaction.addToBackStack(null);
//Commit the transaction
transaction.commit();
}
});
saveButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(isInEditMode)
{
Intent returnIntent = new Intent();
FactFind factFind = new FactFind(titleEditText.getText().toString(),Calendar.getInstance().getTime());
returnIntent.putExtra("FactFind", factFind);
setResult(RESULT_OK, returnIntent);
finish();
}
else
{
isInEditMode = true;
saveButton.setText("Save");
titleEditText.setEnabled(true);
// factFindEditText.setEnabled(true);
}
}
});
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(R.string.are_you_sure_you_want_to_delete_this_fact_find_it_can_t_be_undone_);
builder.setTitle("Confirm Delete");
builder.setPositiveButton("Delete", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent returnIntent = new Intent();
setResult(RESULT_DELETE, returnIntent);
finish();
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
builder.create().show();
return false;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
if (!mNavigationDrawerFragment.isDrawerOpen()) {
// Only show items in the action bar relevant to this screen
// if the drawer is not showing. Otherwise, let the drawer
// decide what to show in the action bar.
getMenuInflater().inflate(R.menu.nav_drawer, menu);
restoreActionBar();
return true;
}
else {
//return super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.action_menu, menu);
return true;
}
}
//#Override
public void onSelectedFragChanged(int index) {
FragmentManager fragmentManager = getFragmentManager();
secA_pg1 secA_pg1 = (secA_pg1) fragmentManager.findFragmentById(R.id.Sec_A_pg1_fragment);
secA_pg1.setSectionTitle(index);
}
public void restoreActionBar() {
ActionBar actionBar = getActionBar();
//actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setTitle(mTitle);
}
#Override
public void onNavigationDrawerItemSelected(int position) {
}
}
and finally my NavigationDrawerFragment java is
/**
* Fragment used for managing interactions for and presentation of a navigation drawer.
* See the <a href="https://developer.android.com/design/patterns/navigation-drawer.html#Interaction">
* design guidelines</a> for a complete explanation of the behaviors implemented here.
*/
public class NavigationDrawerFragment extends Fragment {
/**
* Remember the position of the selected item.
*/
private static final String STATE_SELECTED_POSITION = "selected_navigation_drawer_position";
/**
* Per the design guidelines, you should show the drawer on launch until the user manually
* expands it. This shared preference tracks this.
*/
private static final String PREF_USER_LEARNED_DRAWER = "navigation_drawer_learned";
/**
* A pointer to the current callbacks instance (the Activity).
*/
private NavigationDrawerCallbacks mCallbacks;
/**
* Helper component that ties the action bar to the navigation drawer.
*/
private ActionBarDrawerToggle mDrawerToggle;
private DrawerLayout mDrawerLayout;
private ListView mDrawerListView;
private View mFragmentContainerView;
private int mCurrentSelectedPosition = 0;
private boolean mFromSavedInstanceState;
private boolean mUserLearnedDrawer;
public NavigationDrawerFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Read in the flag indicating whether or not the user has demonstrated awareness of the
// drawer. See PREF_USER_LEARNED_DRAWER for details.
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
mUserLearnedDrawer = sp.getBoolean(PREF_USER_LEARNED_DRAWER, false);
if (savedInstanceState != null) {
mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION);
mFromSavedInstanceState = true;
}
// Select either the default item (0) or the last selected item.
selectItem(mCurrentSelectedPosition);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Indicate that this fragment would like to influence the set of actions in the action bar.
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mDrawerListView = (ListView) inflater.inflate(
R.layout.fragment_navigation_drawer, container, false);
mDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectItem(position);
}
});
mDrawerListView.setAdapter(new ArrayAdapter<String>(
getActionBar().getThemedContext(),
android.R.layout.simple_list_item_activated_1,
android.R.id.text1,
new String[]{
getString(R.string.title_section1),
getString(R.string.title_section2),
getString(R.string.title_section3),
"Assets",
"ID",
}));
mDrawerListView.setItemChecked(mCurrentSelectedPosition, true);
return mDrawerListView;
}
public boolean isDrawerOpen() {
return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(mFragmentContainerView);
}
/**
* Users of this fragment must call this method to set up the navigation drawer interactions.
*
* #param fragmentId The android:id of this fragment in its activity's layout.
* #param drawerLayout The DrawerLayout containing this fragment's UI.
*/
public void setUp(int fragmentId, DrawerLayout drawerLayout) {
mFragmentContainerView = getActivity().findViewById(fragmentId);
mDrawerLayout = drawerLayout;
// set a custom shadow that overlays the main content when the drawer opens
// mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
// set up the drawer's list view with items and click listener
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
// ActionBarDrawerToggle ties together the the proper interactions
// between the navigation drawer and the action bar app icon.
mDrawerToggle = new ActionBarDrawerToggle(
getActivity(), /* host Activity */
mDrawerLayout, /* DrawerLayout object */
// R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */
R.string.navigation_drawer_open, /* "open drawer" description for accessibility */
R.string.navigation_drawer_close /* "close drawer" description for accessibility */
) {
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
if (!isAdded()) {
return;
}
// getActivity().InvalidateOptionsMenu(); // calls onPrepareOptionsMenu()
}
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
if (!isAdded()) {
return;
}
if (!mUserLearnedDrawer) {
// The user manually opened the drawer; store this flag to prevent auto-showing
// the navigation drawer automatically in the future.
mUserLearnedDrawer = true;
SharedPreferences sp = PreferenceManager
.getDefaultSharedPreferences(getActivity());
sp.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).apply();
}
// getActivity().InvalidateOptionsMenu(); // calls onPrepareOptionsMenu()
}
};
// If the user hasn't 'learned' about the drawer, open it to introduce them to the drawer,
// per the navigation drawer design guidelines.
if (!mUserLearnedDrawer && !mFromSavedInstanceState) {
mDrawerLayout.openDrawer(mFragmentContainerView);
}
// Defer code dependent on restoration of previous instance state.
mDrawerLayout.post(new Runnable() {
#Override
public void run() {
mDrawerToggle.syncState();
}
});
mDrawerLayout.setDrawerListener(mDrawerToggle);
}
private void selectItem(int position) {
mCurrentSelectedPosition = position;
if (mDrawerListView != null) {
mDrawerListView.setItemChecked(position, true);
}
if (mDrawerLayout != null) {
mDrawerLayout.closeDrawer(mFragmentContainerView);
}
if (mCallbacks != null) {
mCallbacks.onNavigationDrawerItemSelected(position);
}
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mCallbacks = (NavigationDrawerCallbacks) activity;
} catch (ClassCastException e) {
throw new ClassCastException("Activity must implement NavigationDrawerCallbacks.");
}
}
#Override
public void onDetach() {
super.onDetach();
mCallbacks = null;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(STATE_SELECTED_POSITION, mCurrentSelectedPosition);
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Forward the new configuration the drawer toggle component.
mDrawerToggle.onConfigurationChanged(newConfig);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// If the drawer is open, show the global app actions in the action bar. See also
// showGlobalContextActionBar, which controls the top-left area of the action bar.
if (mDrawerLayout != null && isDrawerOpen()) {
inflater.inflate(R.menu.global, menu);
// showGlobalContextActionBar();
}
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
if (item.getItemId() == R.id.action_example) {
Toast.makeText(getActivity(), "Example action.", Toast.LENGTH_SHORT).show();
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* Per the navigation drawer design guidelines, updates the action bar to show the global app
* 'context', rather than just what's in the current screen.
*/
private void showGlobalContextActionBar() {
ActionBar actionBar = getActionBar();
actionBar.setDisplayShowTitleEnabled(true);
//actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
actionBar.setTitle(R.string.app_name);
}
private ActionBar getActionBar() {
return ((Activity) getActivity()).getActionBar();
}
/**
* Callbacks interface that all activities using this fragment must implement.
*/
public static interface NavigationDrawerCallbacks {
/**
* Called when an item in the navigation drawer is selected.
*/
void onNavigationDrawerItemSelected(int position);
}
}
I've attempted several things and from research and the error I believe one of my XML files is incorrectly laid out and it sees it as a Frame Layout instead of a drawer but I can't figure out exactly where. I've tried amending the layouts in many ways but have had no luck.
Thanks :)
It looks like there's a few things wrong here, unless I'm missing something more complex that you're trying to achieve.
First, when you're using this DrawerLayout, it should have the content and the drawer in separate sections, whereas here everything is grouped under one FrameLayout. The basic structure of the XML would be something like:
<android.support.v4.widget.DrawerLayout>
<FrameLayout>
your main content stuff here
</FrameLayout>
<FrameLayout>
navigationdrawer stuff here
</FrameLayout>
</android.support.v4.widget.DrawerLayout>
They don't have to both be FrameLayouts, but the important thing is that there are two child views and they are in that order. Have a look at the guidance here.
The other main structural thing is that you don't need a DrawerLayout in all of your Fragments as well. The DrawerLayout belongs to the Activity, each fragment can just show its contents.
I believe that your problem is that the FrameLayout content's elements shouldn't contain any other views in your layouts.
For example, in your main fragment, your layout should look like this:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="XXXX.secA_pg1">
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:layout_width="match_parent" android:layout_height="match_parent"
android:text="#string/Sec_A_pg1_fragment"
android:id="#+id/Sec_A_pg1_fragment"
android:layout_below="#id/nextButton"/>
</RelativeLayout>
</android.support.v4.widget.DrawerLayout>
And keep in mind that when calling the isDrawerOpen(View drawer) method, you should pass as the parameter the RelativeLayout (in this example), that's actually the drawer view and also that this view must specify its horizontal gravity with the android:layout_gravity attribute.
I base my answer in the official documentation of DrawerLayout:
https://developer.android.com/training/implementing-navigation/nav-drawer.html

findViewById returning null CustomSource cadslib

I've been trying to use the cardslib lirary in a project I'm working on. I'm trying to use Thumbnail with CustomSource. Everything works as expected. However, when I call findViewById in setupInnerViewElements method on my class that extends Card to find R.id.textview_oferta_preco, it returns null.
Bellow follow my classs and my layouts.
Activity:
public class MenuOpcoes extends AppCompatActivity implements OfertasFragment.OnFragmentInteractionListener, NoticiasFragment.OnFragmentInteractionListener{
private Drawer.Result result = null;
private AccountHeader.Result headerResult = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu_opcoes);
headerResult = new AccountHeader()
.withActivity(this)
.withHeaderBackground(R.drawable.header)
.addProfiles(
new ProfileDrawerItem().withName("Oswaldo Roberto Marques").withEmail("oswaldormarques#gmail.com").withIcon(getResources().getDrawable(R.drawable.profile))
)
.withOnAccountHeaderListener(new AccountHeader.OnAccountHeaderListener() {
#Override
public boolean onProfileChanged(View view, IProfile profile, boolean currentProfile) {
return false;
}
})
.build();
result = new Drawer()
.withActivity(this)
.withTranslucentStatusBar(false)
.withActionBarDrawerToggle(true)
.withAccountHeader(headerResult)
.addDrawerItems(
new PrimaryDrawerItem().withName(R.string.drawer_item_listas).withIcon(FontAwesome.Icon.faw_list),
new PrimaryDrawerItem().withName(R.string.drawer_item_ofertas).withIcon(FontAwesome.Icon.faw_dollar),
new PrimaryDrawerItem().withName(R.string.drawer_item_noticias).withIcon(FontAwesome.Icon.faw_newspaper_o),
new SectionDrawerItem().withName(R.string.drawer_item_section_header),
new SecondaryDrawerItem().withName(R.string.drawer_item_settings).withIcon(FontAwesome.Icon.faw_cog)
)
.withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id, IDrawerItem drawerItem) {
if (drawerItem instanceof Nameable) {
String opcaoSelecionada = MenuOpcoes.this.getString(((Nameable) drawerItem).getNameRes());
FragmentTransaction transaction = getFragmentManager().beginTransaction();
if (opcaoSelecionada.equals("Ofertas")) {
Toast.makeText(MenuOpcoes.this, MenuOpcoes.this.getString(((Nameable) drawerItem).getNameRes()), Toast.LENGTH_SHORT).show();
OfertasFragment ofertasFragment = new OfertasFragment();
transaction.replace(R.id.home_layout_container, ofertasFragment);
transaction.addToBackStack("ofertas");
}
if (opcaoSelecionada.equals(R.string.drawer_item_noticias)) {
Toast.makeText(MenuOpcoes.this, MenuOpcoes.this.getString(((Nameable) drawerItem).getNameRes()), Toast.LENGTH_SHORT).show();
NoticiasFragment noticiasFragment = new NoticiasFragment();
transaction.replace(R.id.home_layout_container, noticiasFragment);
transaction.addToBackStack("noticias");
}
transaction.commit();
}
}
}).build();
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_menu_opcoes, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
//int id = item.getItemId();
//noinspection SimplifiableIfStatement
//if (id == R.id.action_settings) {
// return true;
//}
//return super.onOptionsItemSelected(item);
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onBackPressed() {
//handle the back press :D close the drawer first and if the drawer is closed close the activity
if (getFragmentManager().getBackStackEntryCount() > 0) {
getFragmentManager().popBackStack();
} else {
this.finish();
}
}
#Override
public void onFragmentInteraction(Uri uri) {
}
CustomSource:
public class OfertasCardCustomSource extends Card {
public OfertasCardCustomSource(Context context) {
super(context);
init();
}
public OfertasCardCustomSource(Context context, int innerLayout) {
super(context, innerLayout);
init();
}
private void init() {
CardHeader header = new CardHeader(getContext());
header.setButtonOverflowVisible(true);
header.setTitle("Coca Cola 2,5L");
addCardHeader(header);
CardThumbnail thumbnail = new CardThumbnail(getContext());
thumbnail.setDrawableResource(R.drawable.coca_cola_25l);
addCardThumbnail(thumbnail);
}
#Override
public void setupInnerViewElements(ViewGroup parent, View view) {
TextView title = (TextView) parent.findViewById(R.id.textview_oferta_preco);
title.setText("R$ 4,25");
TextView subtitle = (TextView) parent.findViewById(R.id.textview_oferta_mercado);
subtitle.setText("Mercado Exemplo");
RatingBar mRatingBar = (RatingBar) parent.findViewById(R.id.carddemo_gplay_main_inner_ratingBar);
mRatingBar.setNumStars(5);
mRatingBar.setMax(5);
mRatingBar.setStepSize(0.5f);
mRatingBar.setRating(4.7f);
}
}
Fragment Layout:
<ScrollView
android:id="#+id/card_scrollview"
style="#style/carddemo_default_container_padding"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Custom Source Thumbnail-->
<TextView
style="#style/Theme.Carddemo.TitleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/secao_ofertas"/>
<it.gmariotti.cardslib.library.view.CardViewNative
android:id="#+id/carddemo_thumb_customsource"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="#style/card_external"
card:card_layout_resourceID="#layout/native_card_thumbnail_layout"/>
<!-- Empty view-->
<View
android:layout_width="match_parent"
android:layout_height="15dp"/>
</LinearLayout>
</ScrollView>
CustomSource Layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="60dp"
>
<RatingBar
android:id="#+id/carddemo_gplay_main_inner_ratingBar"
style="#style/carddemo_myapps_main_inner_ratingbar"
android:numStars="5"
android:stepSize="1.0"
android:layout_alignParentLeft="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/textview_oferta_preco"
android:layout_width="wrap_content"
android:textSize="12sp"
android:textColor="#android:color/holo_green_light"
android:layout_alignParentRight="true"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/textview_oferta_mercado"
android:textSize="12sp"
android:textColor="#BBB"
android:layout_alignParentBottom="true"
android:layout_marginBottom="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
I don't know what to do. I'm using Android Studio. Thank you.
When extending Card, you have to call super by passing the layout reference you want to inflate.
I see in your OfertasCardCustomSource class that you have two constructors, one of them receiving a variable innerLayout which is correctly passed to the super class and another constructor that does not set the layout.
Your problem is probably one of the following:
You are not setting the layout in that constructor: you should do something like calling super(context, R.layout.the_layout_of_your_card) - check this reference for a more detailed example
You are not calling the constructor that receives innerLayout anywhere
What I recommend you to do is either delete the constructor that does not receive a layout to be inflated or to pass a default value exactly as it is done in the link I left above.

Can't change the text in TextView of second activity on Android

I'm trying to make an android application. It has two activities: MainActivity and Activity_Service. In MainActivity, there is a button "service" used to pass to Activity_Service. I want to send a string from MainActivity to Activity_Service and then display it in a textview. I would like to show you the codes.
Create the Intent in the MainActivity:
service.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
String message = "bla bla bla";
Intent intent = new Intent(MainActivity.this, ActivityService.class);
intent.putExtra("message", message);
startActivity(intent);
}
});
And onCreate() method in the Activity_Service:
public class ActivityService extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
Bundle bundle = getIntent().getExtras();
String message = bundle.getString("message");
System.out.println(message);
//TextView txtView = new TextView(this);
TextView txtView = (TextView)findViewById(R.id.name);
txtView.setText(message);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_activity,
container, false);
return rootView;
}
}
}
The XML files created by Eclipse while creating the new activity (Activity_Service):
activity_service.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.alljoynandroid.ActivityService"
tools:ignore="MergeRootFrame" />
Fragment_activity.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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.example.alljoynandroid.ActivityService$PlaceholderFragment" >
<TextView
android:id = "#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
In onCreate() method of Activity_Service, if I use TextView txtView = new TextView(this);, It works: It can pass from MainActivity to Activity_Service, but then we can't setText. Other side, if I use TextView txtView = (TextView)findViewById(R.id.name);, it doesn't work all. Could you please help me to solve it? I was trying for 2 days and now I have no idea.
Remove this code part from your Activity
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
and change
setContentView(R.layout.activity_service);
to
setContentView(R.layout.fragment_activity);

Categories

Resources