android nested fragment doesn't work properly - android

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());
}
}
}

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;
}
}

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);

Fragment getView().findViewById(R.id.box1) Returning null

So here's the problem. I'm coding an app with two EditText views inside a fragment and a button. When the button is clicked, it changes the text of the EditText. In the onViewCreated() method I use this code to get the EditText instance and store it to a variable.
EditText box1 = (EditText)(getView.findViewById(R.id.box1));
This works fine. However, when I try to access variable box1 when the button is clicked, the EditText has become null and throws a NullPointerException. Does anyone know why this would happen?
Here is the fragment code:
public class MyFragment extends Fragment {
EditText box1, box2;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_text_coder_free,
container, false);
//Works here.
box1 = (EditText)(rootView.findViewById(R.id.box1));
box2 = (EditText)(rootView.findViewById(R.id.box2));
//Same thing. Sets the text correctly
box1.setText("hey look at me!");
return rootView;
}
//Called when the button is clicked.
public void setBox1Text(String text) {
//It's null here so it skips to the else
if(box1 != null) {
box1.setText(text);
}
else {
//This doesn't work. Throws the exception here.
box1 = (EditText)(getView().findViewById(R.id.box1));
}
}
public void setBox2Text(String text) {
if(box2 != null) {
box2.setText(text);
}
else {
//This doesn't work. Throws the exception here.
box2 = (EditText)(getView().findViewById(R.id.box2));
}
}
public String getBox1Text() {
if(box1 == null) {
return "Nice try.";
}
return box1.getText().toString();
}
public String getBox2Text() {
if(box2 == null) {
return "Nice try.";
}
return box2.getText().toString();
}
}
Here is the activity which houses the fragment:
public class MyActivity extends Activity {
MyFragment myFragment
EditText box1, box2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_text_coder);
if (savedInstanceState == null) {
myFragment = new MyFragment();
getFragmentManager().beginTransaction()
.add(R.id.container, myFragment.commit();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.my_app, 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);
}
public void box1Click(View v) {
myFragment.setBox2Text("Some text");
}
public void box2Click(View v) {
myFragment.setBox2Text("Some text");
}
}
And here is the XML from the fragment:
<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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.mycode.MyFragment" >
<EditText
android:id="#+id/box1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:inputType="textMultiLine" />
<EditText
android:id="#+id/box2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/box1"
android:inputType="textMultiLine|none"
android:focusable="false" />
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/box2"
android:layout_alignParentRight="true"
android:onClick="box2Click" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/encrypt_button_text"
android:layout_below="#id/box2"
android:layout_toLeftOf="#id/button2"
android:onClick="box1Click" />
</RelativeLayout>
Exemple of use:
public class main extends Fragment{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.core_info_tab, container, false);
ImageButton ib = (ImageButton) view.findViewById(R.id.imageButton1);
return view;
}
}
Make sure the fragment is attached to the activity before calling setBox1Text(String text) else the view is not initialized and getView returns null.
There is no need to initialize the edittext again.
You can just have
public void setBox1Text(String text) {
box1.setText(text); // box1 is already initialized in onCreate no need to initialize again
}
If you want use getView use it in onActivtiyCreated
box1 = (EditText)getView().findViewById(R.id.box1));
That's because you're trying to execute setBoxXText(...) before having created the fragment, onCreateView is not yet executed. Be sure that your fragment is loaded before access it's views.
If you check your code, the only way to box1 & box2 to be null is that onCreateView is not yet called, so when you do
if(box1 != null) {
box1.setText(text);
}
else {
and it goes through the else statement, it's because you didn't initialize the fragment.
You have several ways to fix this, for example you can set this values in the fragment initialization (1) or use a listener to notify when the fragment is loaded (2).
1-
Use a factory to initialize your fragment, fragments in android need empty constructors, so in this way you will use an empty constructor and also ensure yourself that in onCreateView you will have setted the box1 and box2 strings
public class YourFragment extends Fragment{
//Empty and private constructor
private YourFragment(){
}
private String box1Text;
private String box2Text;
public void setBox1Text(String box1Text){
this.box1Text = box1Text;
}
public void setBox2Text(String box2Text){
this.box2Text = box2Text;
}
public static YourFragment YourFragmentFactory(String box1Text, String box2Text){
YourFragment result = new YourFragment();
result.setBox1Text(box1Text);
result.setBox2Text(box2Text);
return result;
}
}
and 2:
use a listener to notify your activity when you can start to set the texts:
public interface YourFragmentListener{
public void onViewCreated();
}
private YourFragmentListener listener;
public void setListener(YourFragmentListener listener){
this.listener = listener;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onViewCreated(view, savedInstanceState);
if(this.listener != null){
this.listener.onViewCreated(); 
}
}
To use findViewById you have to execute it on Context (eg. an Activity).
Use: View.getContext().getViewById...
You can also try cleaning the project

Android - keep variable's value in main activity

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.

Categories

Resources