Dynamically update title of Design Support TabLayout - arraylist

is there a way to dynamically update the title of a tab in a Design Support TabLayout? I tried adding a method in the Adapter which changes the contents of the ArrayList which holds the titles of the tabs and notify the adapter but the tab titles don't change to the new title.
Adapter:
public class TabAdapter extends FragmentPagerAdapter {
private final List<Fragment> fragments = new ArrayList<>();
private final List<String> fragmentTiles = new ArrayList<>();
public TabAdapter(FragmentManager fm) {
super(fm);
}
public void addFragment(Fragment fragment, String title) {
fragments.add(fragment);
fragmentTiles.add(title);
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public CharSequence getPageTitle(int position) {
return fragmentTiles.get(position);
}
public void setFragmentTiles(int index, String title) {
fragmentTiles.set(index, title);
Log.e("ARRAY", fragmentTiles.toString());
}
}
I am changing the content of the title ArrayList like this:
adapter.setFragmentTiles("New title 1");
adapter.setFragmentTiles("New title 2");
adapter.notifyDataSetChanged();
But this doesn't work. Do I have to update the ViewPager or the TabLayout as well?

What's worked for me is to use the setText method on the Tab:
i.e. tab.setText(...); // where ... is CharSequence or resId
Looking at the methods available to the TabLayout you can get the desired Tab instance of an index/position:
e.g. tabLayout.getTabAt(...); // where ... is int.
As far as I can tell, calling notifyDataSetChanged() on the adapter just calls the getCount() of the adapter as opposed to what one might expect of refreshing the title.
Hopefully that helps or at least points you in the right direction.

Related

My RecyclerView is duplicated every time I open activity

I have some problem with my project, and I will be very glad if anyone of you helps me. There is an activity in my app, where the only view is RecyclerView and everytime I open this activity, I need fill it, I do it like that:
RecyclerView templatesRecycler;
private MyRecyclerViewAdapter myRecyclerViewAdapter;
int numberOfColumns = 2;
//
templatesRecycler = (RecyclerView) findViewById(R.id.templatesListView);
updateRecyclerView(MyCollections.getTemplatesTitles());
public void updateRecyclerView(ArrayList<MyTemplate> myTemplates){
templatesRecycler.setHasFixedSize(true);
templatesRecycler.setLayoutManager(new GridLayoutManager(this, numberOfColumns));
myRecyclerViewAdapter = new MyRecyclerViewAdapter(this, myTemplates, this);
templatesRecycler.setAdapter(myRecyclerViewAdapter);
}
I want to use class MyCollections, because there are a lot of RecyclerViews in my app, but I dont want to fill it myself everytime, so I create class MyCollections:
public class MyCollections {
public static ArrayList<MyTemplate> templatesTitles = new ArrayList<>();
public MyCollections(){
templatesTitles.add(new MyTemplate("Люди", R.drawable.ic_people));
templatesTitles.add(new MyTemplate("Транспорт", R.drawable.ic_car));
templatesTitles.add(new MyTemplate("Мебель", R.drawable.ic_furniture));
templatesTitles.add(new MyTemplate("Фоны", R.drawable.ic_background));
templatesTitles.add(new MyTemplate("Предметы", R.drawable.ic_tools));
templatesTitles.add(new MyTemplate("Животные", R.drawable.ic_animal));
templatesTitles.add(new MyTemplate("Природа", R.drawable.ic_nature));
templatesTitles.add(new MyTemplate("Разметка листа", R.drawable.ic_sections));
templatesTitles.add(new MyTemplate("Другое", R.drawable.ic_others));
}
public static ArrayList<MyTemplate> getTemplatesTitles() {
return templatesTitles;
}
}
By the way, here is my MyTemplate class:
public class MyTemplate {
public String titleTemplate;
public int drawableID;
public String getTitleTemplate() {
return titleTemplate;
}
public void setTitleTemplate(String titleTemplate) {
this.titleTemplate = titleTemplate;
}
public int getDrawableID() {
return drawableID;
}
public void setDrawableID(int drawableID) {
this.drawableID = drawableID;
}
public MyTemplate(String titleTemplate, int drawableID){
this.titleTemplate = titleTemplate;
this.drawableID = drawableID;
}
public MyTemplate(){}
}
But here is the problem. Every time I open activity, my RecyclerView duplicates his elements, before I filled RecyclerView myself, and there wasnt such a problem. Please, help me, I am just beginner, so I dont know how I can fix this problem. Thanks!

How to see arguments when creating a new class?

When creating a new class or method I used to be able to see the parameters needed. But, now they don't come up anymore. How do I view parameters when creating a class?
Running the latest windows version.
public class Main {
public static void main(String args[]) {
Case theCase = new Case("Default", "Corsair", "500W");
}
}
public class Case {
private String model;
private String manufacturer;
private String powerSupply;
public Case(String model, String manufacturer, String powerSupply,) {
this.model = model;
this.manufacturer = manufacturer;
this.powerSupply = powerSupply;
}
public void pressPowerButton() {
System.out.println("Power button pressed");
}
public String getModel() {
return model;
}
public String getManufacturer() {
return manufacturer;
}
public String getPowerSupply() {
return powerSupply;
}
}
When making theCase I can't see what my parameters are and have to move to the "Case" class back and forth
You can explicitly call Parameter Info action which is usually mapped to Ctrl/(Cmd) - p.
Nevermind in order to see the parameters as you type you must type them while in the editor without moving your cursor.

Showing link inside custom hover (Eclipse plugin development)

I have a custom hover inside CDT editor (see the linked SO question) and now I want to show link inside my IAnnotationHover hover:
public class MyAwesomeHover implements IAnnotationHover {
#Override
public String getHoverInfo(ISourceViewer sw, int ln) {
return "<a href='www.stackoverflow.com'>so</a>"
}
}
Unfortunately the link is not shown - the hover window shows only simple text (i.e "so"). Other HTML elements I tried work OK (ul, li, p, font ...). Can anyone help me please?
As was mentioned in the comments, the RevisionHover was a good starting point. The magic is in implementing the IAnnotationHoverExtension and creation of a custom AbstractReusableInformationControlCreator. I am posting a code snippet with solution that worked for me.
public class MyHover implements IAnnotationHover, IAnnotationHoverExtension {
...
#Override
public IInformationControlCreator getHoverControlCreator() {
return new MyCreator();
}
...
#Override
public Object getHoverInfo(ISourceViewer sv, ILineRange lr, int vnl) {
return "<a href='www.stackoverflow.com'>so</a>";
}
...
private final class MyCreator extends AbstractReusableInformationControlCreator {
protected IInformationControl doCreateInformationControl(Shell parent) {
BrowserInformationControl control =
new BrowserInformationControl(
parent,
JFaceResources.DIALOG_FONT,
false);
control.addLocationListener(
new LocationAdapter() {
#Override
public void changing(LocationEvent ev) {
if (ev.location.startsWith("file:")) {
// !This opens the link!
openUrl(ev.location)
}
}
});
return control;
}
}
}

JavaFX, List to ObservableList to ListView

So my problem is, that I have an serilized ArrayList and have to update it in my GUI to show its content in a ListView dynamically.
The serialization and deserialization works fine with the use of a DAO interface but the GUI won't refresh my ListView.
This class holds my data interaction (mostly save, load...):
public class Medienverwaltung implements Serializable, IDAO{
private static final long serialVersionUID = 1L;
private List<Medium> medienliste;
public ObservableList<Medium> obList; //public for test-reasons
public Medienverwaltung(){
medienliste = new ArrayList<Medium>();
obList = FXCollections.observableArrayList(medienliste);
}
//[...]
public List<Medium> getMedienliste(){
return this.medienliste;
}
//[...]
}
Here comes my GUI implementation snippet:
public class HauptFenster extends Application{
private Medienverwaltung medienverwaltung;
#Override
public void start(Stage stage) throws Exception{
medienverwaltung = new Medienverwaltung();
VBox root = new VBox();
ListView<String> showliste = new ListView<String>();
MenuBar menuBar = createMenuBar(stage);
root.getChildren().add(menuBar);
root.getChildren().add(showliste);
//Make Listener and refresh the shown list!
medienverwaltung.obList.addListener(new ListChangeListener<Medium>(){
#Override
public void onChanged(ListChangeListener.Change<? extends Medium> change) {
showliste.getItems().clear();
for(Medium medium : medienverwaltung.obList){
//toString() is overwritten and works, too
showliste.getItems().add(medium.toString());
}
}
});
// this adds a Medium object to the Arraylist in Medienverwaltung
medienverwaltung.aufnehmen(new Bild("Foto12", 2017, "Zuhause"));
stage.setTitle("Medien Verwaltung");
stage.setScene(new Scene(root, 800, 400) );
stage.show();
}
//[...]
I also tired to exchange the whole ArrayList from the class "Medienverwaltung" with an ObservableList, so that there is only one List remaining, which works for the GUI but not for the serialization and deserialization as I guessed before. (and tried a few other implementations)
Does anyone have an idea how to change my code so that it works?
And my second question is, what is the best way in terms of a 3 layer architecture?
The following is a reference to Fabians Answer and responds to my comment on that
Update#1.1 (addendum for explanation)
public interface IDAO {
// Save method
void speichern(List<Medium> liste) throws PersistenzException;
// Load method
List<Medium> laden() throws PersistenzException;
}
Here comes my concrete save Method:
#Override
public void speichern(List<Medium> medienliste) throws PersistenzException{
File sfile = new File("medienliste.dat");
try(FileOutputStream fos = new FileOutputStream(sfile); ObjectOutputStream oos = new ObjectOutputStream(fos)){
oos.writeObject(medienliste);
System.out.println("Serialisierung erfolgreich!");
}catch(IOException e){
e.printStackTrace();
System.out.println("Serialisierung fehlgeschlagen!");
}
}
Update#1.2 (addendum for explanation)
//[...] section of my GUI for saving
MenuItem speichern = new MenuItem("Speichern");
speichern.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent e){
try{
//Before: medienverwaltung.speichern(medienverwaltung.getMedienliste()); -> doesn't work because of serializing an ObservableList
medienverwaltung.speichern(medienverwaltung.getBackingList());
}catch(PersistenzException pe){
pe.printStackTrace();
}
}
});
//[...]
But as I guess, it's not a fine way to access the backinlist this way.
Update#2:
to respect the principle of encapsulation in a clean way I now added an overloaded Method in the class Medienverwaltung:
public void speichern() throws PersistenzException{
speichern(backingList);
}
So my GUI now only calls speichern(). This actually calls the method for saving with the backedlist which is no more accessible from the outside. I hope this is no bad coding style ^^
BTW.: If you are reading this and have a similar problem, don't use ObservableArrayList for the synchronisation with a normal List, this won't work! Use ObservableList instead.
Hide the backing list (medienliste) from other classes by removing the getter. If you modify this list using the ObservableList the ListView (or every other object that has added a listener to the list) will properly update.
Furthermore unless Medium extends Node you can simply use this kind of object as items of the ListView, since the cells set the text to the result of the toString method called for the associated item by default.
public class Medienverwaltung implements Serializable, IDAO{
private static final long serialVersionUID = 1L;
private List<Medium> backingList;
// transient field not persisted
private transient ObservableList<Medium> medienliste;
public Medienverwaltung(){
backingList = new ArrayList<Medium>();
medienliste = FXCollections.observableArrayList(backingList);
}
// make sure an ObservableList is created when reading the serialized object
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
inputStream.defaultReadObject();
medienliste = FXCollections.observableArrayList(backingList);
}
//[...]
public ObservableList<Medium> getMedienliste(){
return this.medienliste;
}
//[...]
}
#Override
public void start(Stage stage) throws Exception{
medienverwaltung = new Medienverwaltung();
VBox root = new VBox();
ListView<Medium> showliste = new ListView<>(medienverwaltung.getMedienliste());
MenuBar menuBar = createMenuBar(stage);
root.getChildren().add(menuBar);
root.getChildren().add(showliste);
// this adds a Medium object to the Arraylist in Medienverwaltung
medienverwaltung.aufnehmen(new Bild("Foto12", 2017, "Zuhause"));
stage.setTitle("Medien Verwaltung");
stage.setScene(new Scene(root, 800, 400) );
stage.show();
}
Note that the Medienverwaltung.aufnehmen method should not work directly with the backing list - it should use the ObservableList instead to make sure changes can be observed...
EDIT
Looking at the IDAO interface it should probably be a object different to Medienverwaltung, since otherwise you'd violate the seperation of concerns design principle; also it wouldn't make sense to pass a value as parameter that's already contained as property of the object itself.
It seems that the IDAO object should be responsible for reading/writing the list data only which would make implementing Serializable with Medienverwaltung unnecessary. Probably something like this is expected solution to your excercise:
IDAO idao = new IDAOImplementation();
Medienverwaltung medienverwaltung = new Medienverwaltung(idao.laden());
public void handle(ActionEvent e){
try{
idao.speichern(medienverwaltung.getMedienliste());
}catch(PersistenzException pe){
pe.printStackTrace();
}
}
public Medienverwaltung(List<Medium> medien) {
this.medienliste = FXCollections.observableArrayList(medien);
}
The IDAO implementation should most likely not depend on the implementation of the List and therefore not expect the List to be serializable. You can simply work around non-serialized lists by a) not using ObjectOutputStream to persist the data, but some other way not relying on serializable objects or b) simply copy the contents of the list to a serializable list:
#Override
public void speichern(List<Medium> medienliste) throws PersistenzException{
File sfile = new File("medienliste.dat");
try(FileOutputStream fos = new FileOutputStream(sfile); ObjectOutputStream oos = new ObjectOutputStream(fos)){
oos.writeObject(new ArrayList(medienliste));
System.out.println("Serialisierung erfolgreich!");
} catch(IOException e){
throw new PersistenzException(e);
}
}

GWTP: Troubles to display a CellTable

Hi I'm new to GWT and so, to GWTP too.
I try to play with CellTables and I decided to begin by building a simple one following GWT documentation at developers.google.com/web-toolkit/doc/2.4/DevGuideUiCellWidgets#celltable
I adapted few things to match GWTP MVP design.
First, I created my Celltable on my View.ui.xml file:
xmlns:c="urn:import:com.google.gwt.user.cellview.client">
<g:HTMLPanel>
<c:CellTable pageSize='15' ui:field='cellTable' />
</g:HTMLPanel>
Then, I created a class Contact:
public class Contact {
private final String address;
private final String name;
public Contact(String name, String address) {
this.name = name;
this.address = address;
}
public String getAddress() {
return address;
}
public String getName() {
return name;
}
}
in my View.java file:
#UiField(provided=true) CellTable<Contact> cellTable = new CellTable<Contact>();
public CellTable<Contact> getCellTable() {
return cellTable;
}
Finally in my Presenter.java file:
public interface MyView extends View {
CellTable<Contact> getCellTable();
}
#Override
protected void onReset() {
super.onReset();
// Create name column.
TextColumn<Contact> nameColumn = new TextColumn<Contact>() {
#Override
public String getValue(Contact contact) {
return contact.getName();
}
};
// Create address column.
TextColumn<Contact> addressColumn = new TextColumn<Contact>() {
#Override
public String getValue(Contact contact) {
return contact.getAddress();
}
};
// Add the columns.
getView().getCellTable().addColumn(nameColumn, "Name");
getView().getCellTable().addColumn(addressColumn, "Address");
// Set the total row count.
getView().getCellTable().setRowCount(CONTACTS.size(), true);
// Push the data into the widget.
getView().getCellTable().setRowData(0, CONTACTS);
}
Everything seems good to me but there is no CellTable displayed when I try this code...And I get no errors...
Thanks in advance for your Help!
It looks like you do not use/have DataProvider registered for your CellTable. GWT CellWidgets are based on DataProvider/DIsplay pattern. So CellTable is just a Display for your DataProvider. One DataProvider could have multiple displays.
You do not need to write:
// Set the total row count.
getView().getCellTable().setRowCount(CONTACTS.size(), true);
// Push the data into the widget.
getView().getCellTable().setRowData(0, CONTACTS);
You need to register your CellTable as a Display for your DataProvider (eg ListDataProvider) and than call refresh method when you update DataProvider with new data.