I have put Caldroid inside my activity with this code in onCreate method.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
app_font = Typeface.createFromAsset(getAssets(), "custom_font.ttf");
dbHelper = new DatabaseHelper(this);
caldroidFragment = new CaldroidFragment();
if (savedInstanceState != null) {
caldroidFragment.restoreStatesFromKey(savedInstanceState,
"CALDROID_SAVED_STATE");
} else {
Bundle args = new Bundle();
args.putInt(CaldroidFragment.MONTH, calendar.get(Calendar.MONTH) + 1);
args.putInt(CaldroidFragment.YEAR, calendar.get(Calendar.YEAR));
args.putBoolean(CaldroidFragment.ENABLE_SWIPE, true);
args.putBoolean(CaldroidFragment.SIX_WEEKS_IN_CALENDAR, true);
args.putInt(CaldroidFragment.START_DAY_OF_WEEK, CaldroidFragment.MONDAY);
caldroidFragment.setArguments(args);
}
FragmentTransaction t = getSupportFragmentManager().beginTransaction();
t.replace(R.id.calendar_holder, caldroidFragment, FRAGMENT_TAG);
t.commit();
fragmentMounted = true;
CaldroidListener listener = new CaldroidListener() {
#Override
public void onSelectDate(Date date, View view) {
Intent k = new Intent(MainActivity.this, DateActivity.class);
k.putExtra(TIME, date.getTime());
MainActivity.this.startActivity(k);
}
#Override
public void onChangeMonth(int month, int year) {
if (marker != null) {
marker.stopWorking();
}
marker = new DateMarker(MainActivity.this, month, year);
marker.start();
}
#Override
public void onLongClickDate(Date date, View view) {
// do nothing
}
#Override
public void onCaldroidViewCreated() {
// do nothing
}
};
caldroidFragment.setCaldroidListener(listener);
}
As you notice, there is a Thread being called inside listener every time user switches to other month. This thread accesses database and marks dates which have events.
NOTE: this is just inner sample of code inside run method of that thread.
// more code above
if (MainActivity.dbHelper.getNotesOnDate(date).size() == 0) {
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
activity.caldroidFragment.setBackgroundResourceForDate(R.color.SeaGreen, date);
activity.caldroidFragment.setTextColorForDate(R.color.white, date);
activity.caldroidFragment.refreshView();
}
});
}
//more code under
I start another activity for user to log in while all this loads. The problem is only markings that are made BEFORE replacing fragment with holder view in onCreate method. How can I refresh caldroidFragment after replacing it with its holder? refreshView() seems not to be working after placing it.
EDIT: I did research and I notice Caldroid is using app V4 Fragment. I tried to detach and reattach it to get refresh effect but I only got NullPointerException while trying to do it.
I found the answer, do not use Java's Date class, it does not work right.
Use Joda's DateTime. Caldroid works fine with it. Also, I found minor bug in my database access, but it should have worked even though it was there.
Related
I've made a list made of TextViews and Buttons, made that when a person clicks on a button, a fragment opens and there is a list of values he can select. The problem is when i press on another button to select a value again for a different field, the previous value disappears. So the question would be how to save the fragments values, and keep it saved until the app is closed ?
priceButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
PriceFragment priceFragment = new PriceFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.fragmentContainer, priceFragment).commit();
setToHideElements();
}
});
yearButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
YearFragment yearFragment = new YearFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.fragmentContainer, yearFragment).commit();
setToHideElements();
}
});
this is the year fragment
yearEndListView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(getActivity().getBaseContext(), MainMenuActivity.class);
String yearTo = yearList[i].toString();
int yearTint = Integer.valueOf(yearTo);
if (combinedYear != null) {
combinedYear = combinedYear + " " + yearTo;
intent.putExtra("Years", combinedYear);
getActivity().startActivity(intent);
} else {
combinedYear = null;
combinedYear = yearTo;
}
}
});
this is the method to retrive data
private void retriveDataFromFragment(){
Intent intent = getIntent();
String fragmentDataPrice = intent.getStringExtra("PriceData");
String fragmentDataYear = intent.getStringExtra("Years");
if(fragmentDataPrice != null){
priceButton.setText(fragmentDataPrice);
} else {}
if (fragmentDataYear != null){
yearButton.setText(fragmentDataYear);
} else {}
}
I use RetriveDataFromFragment method in OnResume method.
Thank you, for your time.
you are initiating every time a new fragment so it will never retain its state. you have to use listener while closing the fragment so you can get back your data.
I got the anwser if someone else needs a similar menu, all you have to do is create a class that extends Application, and include into your manifest (the part with application tags). From there you just use getters and setters and all is well.
So im quite new to Android Studio and app development in general and i had this issue for a while, with no luck of fixing it. I've figured that someone here might provide some ideas for fixing this..
Issue: The refreshing of ListView on UI thread (as suggested here) does not work for me. Here's the declaration of 'Runnable run' (in MainActivity.java):
public Runnable run;
// ...
run = new Runnable() {
public void run() {
ArrayList<String> temp1 = (ArrayList<String>) arrayList_1.clone();
View v = getLayoutInflater().inflate(R.layout.fragment_main, null);
lv_1 = (ListView) v.findViewById(R.id.listViewMe);
lv_1.setAdapter(adapter_1);
arrayList_1.clear();
arrayList_1.addAll(temp1);
adapter_1.notifyDataSetChanged();
lv_1.invalidateViews();
lv_1.refreshDrawableState();
Log.e("gig", "DONE REFRESHING");
}
};
I call the method here:
#Override
public boolean onNavigationItemSelected(MenuItem item)
{
int id = item.getItemId();
Fragment fragment = null;
if (id == R.id.nav_main) {
fragment = new FragmentMain();
} if (id == R.id.nav_history) {
fragment = new FragmentHistory();
}
if (fragment != null)
{
FragmentTransaction localFragmentTransaction = getSupportFragmentManager().beginTransaction();
localFragmentTransaction.replace(R.id.screen_area, fragment);
localFragmentTransaction.commit();
runOnUiThread(run); // here
}
((DrawerLayout) findViewById(R.id.drawer_layout)).closeDrawer(GravityCompat.START);
return true;
}
Now for the part that's confusing me: it works when i add a new item to the ListView via this method:
public void addDebtToOther(String name, String money)
{
String full = name + ", " + money + " EUR";
lv_1 = (ListView) findViewById(R.id.listViewMe);
if (lv_1!=null) {
lv_1.setAdapter(adapter_1);
arrayList_1.add(full);
adapter_1.notifyDataSetChanged();
} else {
Log.e("gig", "ListView error, lv is NULL");
}
}
That's about it, any help would be really apriciated!
In the run object, a new View is inflated, but as far as I can tell, it's not being added to the Activity's contentView or any of it's children, so it is just a View somewhere in memory that isn't being rendered onto the screen.
Did you mean to do something like this instead?:
public Runnable run;
// ...
run = new Runnable() {
public void run() {
ArrayList<String> temp1 = (ArrayList<String>) arrayList_1.clone();
// View v = getLayoutInflater().inflate(R.layout.fragment_main, null);
// lv_1 = (ListView) v.findViewById(R.id.listViewMe);
lv_1 = (ListView) findViewById(R.id.listViewMe);
lv_1.setAdapter(adapter_1);
arrayList_1.clear();
arrayList_1.addAll(temp1);
adapter_1.notifyDataSetChanged();
lv_1.invalidateViews();
lv_1.refreshDrawableState();
Log.e("gig", "DONE REFRESHING");
}
};
Ok so after about a week of head-banging, with the help of #Eric i've figured it out. Turns out i needed to call the run() method in my fragment's .onStart(), like this:
#Override
public void onStart() {
super.onStart();
((MainActivity)getContext()).run.run();
}
Thanks again Eric!
I have a tabhost with several tabs and each tab contain a certain number of operations which are listed in a listview. To populate that listview I use an ArrayList.
First time tabs are created evertything works fine. The issue comes when I try to filter the list by year. The process of filtering works fine as I can see the filtered list in debug and it's fine.
The issue is that after filtering, i recreate the tabs in order to fill all listviews again. To open tabs I use this code. It creates as many tabs as different currencies there are in the list:
public static void openFragments(FragmentTabHost tabHost, ArrayList<Posicion> positions, Class FragmentResumen, Class FragmentDetails ) {
//==========================================================================================
// This method open as many tabs as different currencies there are in positions list
//==========================================================================================
ArrayList<String> currencies = Currency.getDifferentCurrencies(positions);
tabHost.clearAllTabs();
for (int i = 0; i < currencies.size() + 1; i++) {
String tabName = "", tabSpec = "";
Class fragmentToOpen;
Bundle arg1 = new Bundle();
//A general tab is first created
if (i == 0)
{
tabName = "All";
tabSpec = "General";
arg1.putString("moneda", tabName);
arg1.putSerializable("posiciones", positions);
fragmentToOpen = FragmentResumen;
}
//The rest of tabs for currencies are created
else
{
tabName = currencies.get(i - 1);
tabSpec = "Tab" + (i - 1);
arg1.putString("moneda", tabName);
arg1.putSerializable("posiciones", positions);
fragmentToOpen = FragmentDetails;
}
tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(tabName), fragmentToOpen, arg1);
}
}
As I told before, this works fine always.
First time I need to create tabs I call it by using:
openFragments(tabHost, positions, FragmentResumenMedio.class, FragmentDetailsMedio.class);
Then I have a button that shows a DatePicker and when user selects a year I close the dialog and redraw tabs as follows:
ArrayList<Posicion> positionsFiltered = General.makeHardCopyOfArrayListPosition(positions);
for(Posicion posicion : positionsFiltered)
{
Boolean matchFilters = filterPositionsByYear(posicion, year + "");
if(matchFilters == false){
positions.remove(posicion);
}
}
General.openFragments(tabHost, positions, FragmentResumenMedio.class, FragmentDetailsMedio.class);
When I debug this last function I can see that positions have the correct value after filtering but when I click the new tab, it shows the list without filtering and I don't know how could I solve this issue.
Thanks a lot.
EDIT
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//Initialize view and tabhost
View rootView = inflater.inflate(R.layout.fragment_medio, container, false);
tabHost = (FragmentTabHost) rootView.findViewById(android.R.id.tabhost);
tabHost.setup(getActivity(), getChildFragmentManager(), android.R.id.tabcontent);
return tabHost;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//onCreatedView is only called the first time so we must ensure that tabhost is not null before adding tabs
if(tabHost == null) {
tabHost = (FragmentTabHost) getView().findViewById(android.R.id.tabhost);
tabHost.setup(getActivity(), getChildFragmentManager(), android.R.id.tabcontent);
}
FloatingActionButton floatingActionButton = (FloatingActionButton) getView().findViewById(R.id.floatingButton);
floatingActionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
positions = new ArrayList<>(positionsFiltered);
createDialogWithoutDateField().show();
}
});
//Check if any update has been made since the last open
SharedPreferences prefs = getActivity().getPreferences(MODE_PRIVATE);
Boolean updateMedioRequired = prefs.getBoolean(updateOperationsMedioPlazo, true);
if (updateMedioRequired != null)
{
if (updateMedioRequired == true)
{
//Update variable that indicates if changes have been made or not
SharedPreferences.Editor editor = getActivity().getPreferences(MODE_PRIVATE).edit();
editor.putBoolean(updateOperationsMedioPlazo, false);
editor.apply();
//Check if there are previously stored operations
if (operations.size() > 0)
{
//Show a progressDialog as prices have to be downloaded from internet and this can be a time consumming task
progress = ProgressDialog.show(getActivity(), "Obteniendo precios",
"Un momento por favor...", true);
//Generate positions from operations list and wait for result in "onStockPriceResult". If there are no changes, positions variable has already values
if(positions.size() == 0) {
new Thread(new Runnable() {
#Override
public void run() {
positions = MedioPlazoCalculations.generatePositions(listener, getActivity(), operations);
}
}).start();
}
}
else
{
Toast.makeText(getActivity(), "Aún no se ha introducido ninguna operación", Toast.LENGTH_LONG).show();
}
}
else
{
//If no update needed, variable coming from MainActivity has positionList. Open as many new fragments as currencies there are in positionsList
General.openFragments(tabHost, positions, FragmentResumenMedio.class, FragmentDetailsMedio.class);
}
}
}
EDIT 2:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
{
if(getActivity()!=null)
{
Bundle bundle = this.getArguments();
positions = (ArrayList<Posicion>) bundle.getSerializable("posiciones");
moneda = (String) bundle.getString("moneda");
}
}
}
Edit 3: If I place the commented instruction, filtering does not work. If I remove it, filtering works but I cant filter again because the value of the list has the filtered version not the original one
floatingActionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
positions = new ArrayList<>(positionsFiltered);
createDialogWithoutDateField().show();
}
});
This is my onClick information:
Button searchButton = (Button) findViewById(R.id.search_button);
searchButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
BookListFragment bookListFragment = new BookListFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.book_list_frame, bookListFragment).commit();
}
});
BookListFragment w/BookLoader:
#Override
public Loader<List<BookListing>> onCreateLoader(int i, Bundle args) {
return new BookLoader(this, GOOGLE_BOOKS_URL + searchedBook);
}
#Override
public void onLoadFinished(Loader<List<BookListing>> loader, List<BookListing> bookListings) {
mAdapter.clear();
if(bookListings != null && !bookListings.isEmpty()) {
mAdapter.addAll(bookListings);
}
}
#Override
public void onLoaderReset(Loader<List<BookListing>> loader) {
mAdapter.clear();
}
I am able to get search results. But when searching again the previous results don't clear. They just continuously overlap.
First Search Screenshot
Second Search Screenshot
#Override
public Loader<List<BookListing>> onCreateLoader(int i, Bundle args) {
return new BookLoader(this, GOOGLE_BOOKS_URL + searchedBook);
}
#Override
public void onLoadFinished(Loader<List<BookListing>> loader,
List<BookListing> bookListings) {
mAdapter.clear();
if(bookListings != null && !bookListings.isEmpty()) {
mAdapter.replace(bookListings);
}
}
#Override
public void onLoaderReset(Loader<List<BookListing>> loader) {
mAdapter.clear();
}
When adding a BookListFragment, use replace() instead of add()
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.book_list_frame, bookListFragment)
.commit();
Hope it helps
You have to use replace() instead of add()
getSupportFragmentManager().beginTransaction()
.replace(R.id.book_list_frame, bookListFragment).commit();
That should do it
This is one solution. Remove all child views (rows) by first getting their parent (ListView).
public void removeView(View v) {
if(v.getParent() != null) {
((ViewGroup) v.getParent()).removeView(v);
}
}
Call removeView(v) for every row in your ListView. In this case all rows share one parent so try making that parent an instance field and then method above will be:
ListView listView;
. . .
public static void removeView(View v) {
listView.removeView(v);
}
You can also remove all rows with one single call by:
listView.removeAllViews();
Hope this helps!
difference between fragmentTransaction.add and fragmentTransaction.replace
Just further adding onto CamiloCons answer, you're "adding" a new layer of fragments on top everytime you call add().
I am using a ListFragment for displaying a list from a database in my activity. I have included a search function. Unfortunately the "old" ListFragments seem to remain in the background and the ListFragments containing the result of the query are displayed on top of it. How can I avoid, that the old ListFragments are displayed?
My FragmentActivity:
private Button buttonSearch;
private TextView searchString;
public static String search = null;
static IShoppinglist shoppinglistManager;
static IAktionen aktionenManager;
private AktionenListListFragment listFragment;
#Override
public void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "ListFragmentActivity created");
super.onCreate(savedInstanceState);
setContentView(R.layout.articlelist);
shoppinglistManager = new Shoppinglist(this);
aktionenManager = new Aktionen(this);
buttonSearch = (Button) findViewById(R.id.search_Button);
buttonSearch.setOnClickListener(searchListAktionen);
//show all entries on start
listFragment = new AktionenListListFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_articlelist, listFragment).commit();
}
OnClickListener searchListAktionen = new OnClickListener() {
public void onClick(View v) {
try{
searchString = (TextView) findViewById(R.id.input_search_bezeichnung);
search = searchString.getText().toString().trim();
Log.d(TAG, "search Button clicked "+search);
if(search.trim().length()==0){
search=null;
}
//show all entries on start
listFragment = new AktionenListListFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_articlelist, listFragment).commit();
}catch(Exception ex){
ex.printStackTrace();
}
}
};
Thanks in advance,
update:
thank you for your answers. I tried to implement them, but the main problem seems to be nowthat the onCreate and onActivityCreated method in the ListFragment are called twice (as I can see in my log messages).
my new code:
#Override
public void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "ListFragmentActivity created");
super.onCreate(savedInstanceState);
//force commit
getSupportFragmentManager().executePendingTransactions();
if(getSupportFragmentManager().findFragmentByTag(tag) == null) {
setContentView(R.layout.articlelist);
shoppinglistManager = new Shoppinglist(this);
aktionenManager = new Aktionen(this);
buttonSearch = (Button) findViewById(R.id.search_Button);
buttonSearch.setOnClickListener(searchListAktionen);
listFragment = new AktionenListListFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_articlelist, listFragment,tag).commit();
}else{
Log.d(TAG, "ListFragment already exists");
}
}
I tried to set a unique tag for my ListFragment but this solution does not work.
I guess that one of the ListFragments is displayed in the background and the other is updated.
So first you need to stop making new ListFragments everytime your list is refreshed and just have a public method in your ListFragment that the Activity can call to restart the loader with the proper parameters. Then:
In your onLoadFinished(),
you should make a new adapter with the list you want to replace it with
myAdapter = new AktionenListCustomCursorAdapter(getActivity(), myCursor);
and call:
this.getListView().setAdapter(myAdapter);
So:
public void onLoadFinished(Loader<Cursor> mAdapter, Cursor myCursor) {
if(myCursor!=null){
//getting the data from the database
Log.d(TAG, "search String "+AktionenListFragmentActivity.search);
if(AktionenListFragmentActivity.search==null){
myCursor = AktionenListFragmentActivity.aktionenManager.fetchAllArticles();
}else{
myCursor = AktionenListFragmentActivity.aktionenManager.fetchItemsByBezeichnung(AktionenListFragmentActivity.search);
}
myAdapter = new AktionenListCustomCursorAdapter(getActivity(), myCursor);
this.getListView().setAdapter(myAdapter);
}
}
Hopefully this solved your question as I understood it. If you have any questions please leave it in the comment below and I will expand my answer. If it worked for you please accept answer. :D