I want to create button dynamically in my application. The buttons need to be created based on items fetched from database. What is the best way to achieve this. Should I go for grid layout or Linear layout. My layout is simple with max 3 buttons per row. Once the first row is complete the buttons should be placed in second row.
I scanned lot of similar questions(some had grid layout other were using Linear layout) but unable to decide what is the optimum way to implement this.
I am complete newbie in android application, so any code snippets would be really helpful. Apologies if someone feels this is a duplicate question (I searched a lot before posting but didn't find appropriate answer to layout to be used.)
Thanks.
Please try to use gridView same as bellow code.
// in xml write this code
<GridView
android:id="#+id/calendar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:numColumns="3" />
// grid adapter
public class GridAdapter extends BaseAdapter {
private final Context _context;
private final List<String> list;
public GridAdapter(Context context, ArrayList<String> list) {
super();
this._context = context;
this.list = list;
}
public String getItem(int position) {
return list.get(position);
}
#Override
public int getCount() {
return list.size();
}
public View getView(int position, View convertView, ViewGroup parent) {
Button button = new Button(_context);
button.setText("button" + list.get(position));
return button;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
}
/// in oncreate
gridView.setAdapter(new GridAdapter(getApplicationContext(),list);
Related
To illustrate what I mean with this, it is similar to WhatsApp, where various options are displayed in the toolbar when a chat is selected.
I have a similar layout, so a MainActivity with Fragments containing RecyclerViews. Now when an item in a RecyclerView is selected I would like to get a similar behaviour as in WhatsApp. The RecyclerViews have an Adapter that implements an OnClickListener.
However, from this Adapter I do not seem to have access to Views from the MainActivity. I tried the following (inside the OnClick method in the Adapter), but it did not work since the view could not be found.
View view = getActivity().findViewById(R.id.toolbar_main_activity);
if( view instanceof Toolbar) {
Toolbar toolbar = (Toolbar) view;
toolbar.setTitle("TestTitle");
}
Does anyone know how to get the intended behavior or have a reference to a tutorial?
UPDATE: for who is also stuck with this and this is still quite confusing, here is how I solved it in my own words
My Fragment contains the Interface by adding the following code to it;
OnItemsSelected mCallBack;
public interface OnItemsSelected {
void onToolbarOptions(String title);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
mCallback = (OnItemsSelected) getActivity();
}
Also I passed 'mCallback' to the adapter like this;
MyAdapter adapter = new MyAdapter(myList, mCallback);
The RecyclerView adapter implements OnClickListener. In the OnClick method I called; 'mCallBack.onToolbarOptions("someTitle");'. And finally I made my MainActivity implement the method; 'implements myFragment.onItemsSelected' and I added the following code to it also;
#Override
public void onToolbarOptions(String title) {
toolbar.setTitle(title);
}
With this, only the title is changed, but from this it is quite easy to make other changes to the toolbar, such as changing the menu items.
Inside your Fragment you make an Interface and a global variable like this:
OnItemsSelected mCallBack;
public interface OnItemsSelected {
public void onToolbarOptions();
}
Then when in your RecyclerView items are selected or clicked you call:
mCallBack.onToolbarOptions();
In your Activity implement the Interface like this plus the method onToolbarOptions():
public static class YourActivityName extends AppCompatActivity
implements YourFragmentName.OnItemsSelected {
public void onToolbarOptions(){
// CHANGE YOUR TOOLBAR HERE
}
//.....OTHER STUFFS IN YOUR ACTIVITY
}
My CardView duplicate elements upon data change, the vardView is within a tab, and the way i declared that tab fragment as following;
in the onCreateView, i declared all the necessary firebase links and value events listeners to retrieve the required data related to the elements displayed on the cards.
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
if(snapshot !=null){
for (DataSnapshot child: snapshot.getChildren()) {
Log.i("MyTag", child.getValue().toString());
imagesfeedsList.add(child.child("address").getValue(String.class));
authorfeedsList.add(child.child("author").getValue(String.class));
ratingfeedsList.add(child.child("rating").getValue(String.class));
locationfeedsList.add(child.child("location").getValue(String.class));
publicIDfeedsList.add(child.child("public_id").getValue(String.class));
}
Log.i("MyTag_imagesDirFinal", imagesfeedsList.toString());
mImages = imagesfeedsList.toArray(new String[imagesfeedsList.size()]);
author = authorfeedsList.toArray(new String[authorfeedsList.size()]);
ratingV = ratingfeedsList.toArray(new String[ratingfeedsList.size()]);
locationV = locationfeedsList.toArray(new String[locationfeedsList.size()]);
publicID = publicIDfeedsList.toArray(new String[publicIDfeedsList.size()]);
numbOfAdrs = Long.valueOf(imagesfeedsList.size());
LENGTH = Integer.valueOf(String.valueOf(numbOfAdrs));
}
right after the snippet the adapter setup;
ContentAdapter adapter = new ContentAdapter(recyclerView.getContext());
recyclerView.setAdapter(adapter);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
return recyclerView;
}
Then comes the view holder with a RecycleView, declaring the cardView elements. One of the elements is a ratingBar, and here where the ratingbar Listener is to submit the user rating on a specific picture.
after that the content adapter;
public static class ContentAdapter extends RecyclerView.Adapter<ViewHolder> {
// Set numbers of List in RecyclerView.
private Context mContext;
public ContentAdapter(Context context) {
this.mContext = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()), parent);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.authorName.setText(author[position]);
holder.ratingValue.setText(ratingV[position]);
holder.locationValue.setText(locationV[position]);
Picasso.with(mContext).load(mImages[position]).into(holder.picture);
#Override
public int getItemCount() {
return LENGTH;
}
}
My problem is whenever the user submits a rating or even when the data related to any of the elements on anycard changes, the view gets duplicated ( i mean by the view, the cards ), a repetition of the cards, with the new data chnages displayed ?
i a not sure what is in my above code structure causing this and how to fix this repetitions, i mean i need the cards to be updated with the new data but not duplicated?
All right, so the problem was that every time the data changes, in the onCreate the imagesFeedList, ratingFeedList, etc does not get rid of the old information stored in it from the initial build, so when the refresh happens triggered by onDataChange, the new information gets added to the previous information, which cause the view to repeat the cards, thus just at the beginning of onDataChange and before storing any information in the several feedLists, it must be cleared;
imagesfeedsList.clear();
authorfeedsList.clear();
ratingfeedsList.clear();
locationfeedsList.clear();
publicIDfeedsList.clear();
and by that i made sure the view does not repeat build up based on old information.
I am trying to created a listview containing filenames. I want to set a additional information like file id with each list items, so when i click a filename, i have to get file id from it. please help me do this.
My sample code:
ListView listview = (ListView) findViewById(R.id.listview);
ArrayAdapter fileListAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, ['one','two','three']);
listview.setAdapter(fileListAdapter);
There are quite a few things involved here, so i'm providing you with an example of how you can achieve this (you can copy-paste and test):
public class MainActivity extends ListActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// First we simulate a pool of file names and IDs
String[] fileNames = {"fileName1", "fileName2", "fileName3"};
List<Integer> fileNameIds = new ArrayList<Integer>();
fileNameIds.add(1200);
fileNameIds.add(356);
fileNameIds.add(28);
// We call our custom Adapter
ArrayAdapter<String> adapter = new CustomAdapter(this, fileNames, fileNameIds);
// Finally we set the adapter to our list
setListAdapter(adapter);
}
// This is a custom adapter that uses ArrayAdapter for our purpose
// (as this is just an example you should consider using Base Adapter if you don't want
// to have a pool of filenames and a separate pool of ids)
class CustomAdapter extends ArrayAdapter<String>{
private final LayoutInflater INFLATER;
private final String[] FILE_NAMES;
private final List<Integer> FILE_NAME_IDS;
public CustomAdapter(Context context, String[] fileNames, List<Integer> fileNameIds) {
super(context, R.layout.custom_row, fileNames);
this.INFLATER = LayoutInflater.from(context);
this.FILE_NAMES = fileNames;
this.FILE_NAME_IDS = fileNameIds;
}
// HERE is where you can assign effectively an ID to your rows
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// this is an object that takes advantage of the holder pattern
// it retains the state of our rows in the list
FileNameHolder holder;
if(convertView == null){
convertView = INFLATER.inflate(R.layout.custom_row, null); // inflate your custom row
// now you need to assign specific identifier to the list row that the holder will retain
// for you, so you can always get this id by calling getTag from the View object on your
// item click listeners
holder = new FileNameHolder();
holder.fileName = (TextView) convertView; //since i only have a texView in layout i don't need to call findByView
convertView.setTag(holder); // relate the view to a custom FileNameHolder object that retains file name and its ID
} else{
holder = (FileNameHolder) convertView.getTag();
}
holder.fileName.setText(FILE_NAMES[position]); // PROVIDE the list with file name description
holder.idFileName = FILE_NAME_IDS.get(position); // ASSIGN file name ID
return convertView;
}
}
// This is an example of catching a row clicked and get the custom ID that you assigned,
// from here you can use that ID as you need
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// Here as you can see we obtain the object associated with the row that was clicked
FileNameHolder holder = (FileNameHolder) v.getTag();
// Here i provide a way you can test that you're always getting the correct file name and Id
Toast.makeText(this,
"File Name = " + holder.fileName.getText() +
", File ID = " + holder.idFileName,
Toast.LENGTH_SHORT).show();
}
// This is a class that takes advantage of the Holder Pattern and we use it to
// achieve what you need (remember this is just an example you should consider
// changing class and member access modifiers as you need)
class FileNameHolder{
Integer idFileName;
TextView fileName;
FileNameHolder() {
}
}
}
custom_row.xml is just a TextView (i took it from the simple_list_item_1 layout):
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:paddingStart="?android:attr/expandableListPreferredItemPaddingLeft"
android:textAppearance="?android:attr/textAppearanceMedium"
android:gravity="center_vertical"
/>
Hope it's useful... regards!!
i working little bit with the ListView from JavaFx2. I´m running into one issue.
Is it possible to turn off the clipping of the ListCell/ListView?
I add an ImageView that has to be wider than the ListView and JavaFx2 shows automatically a scrollbar.
This my code snipped how i add the ImageView to my List:
list.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
#Override
public ListCell<String> call(ListView<String> param) {
final ListCell<String> blub = new ListCell<String>() {
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
StackPane p = new StackPane();
Label label = new Label(item);
p.getChildren().addAll(img, label);
setGraphic(p);
p.setAlignment(Pos.CENTER_LEFT);
}
}
};
blub.setStyle("-fx-background-color:transparent");
return blub;
}
});
Big thanks!
I don't think it's possible.
Maybe try to play with the Skin of the ListView. It seems that the scroll bar are managed in this class. It do not use a scroll pane.
Another solution could be replacing the ListView by a VBox in a ScrollPane.
Finally, you could try to modify img (by the way, where it come from, and what Class is it ?) to only show what you need.
Anyway, I'm interested by the solution you will use.
I have Three Spinners= spinState,spinCounty,& spinCity, i would like to select the State spinner then choose a State,then the second spinner would give me the list of Counties within that particular state,then select the County,then the third spinner would give me a list of the cities with in that particular county,such as: (State)Florida,(County)Dade,(City)Miami then after all 3 have been selected pass that information to the next Activity/Class. Can anyone help? here is my code
Spinner spinState,spinCounty,spinCity;
Button bNext;
protected void onCreate(Bundle)
{
//TODO Auto generated method stub
super.oncreate(Bundle)
setContentView(R.layout.info);
Spinner States = (Spinner) findViewById(R.id.spinState);
ArrayAdapter USstates = ArrayAdapter.createFromResource(this,
R.array.States, android.R.layout.simple_spinner_item);
USstates.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
States.setAdapter(USstates);
Spinner Counties = (Spinner) findViewById(R.id.spinCounty);
ArrayAdapter UScounties = ArrayAdapter.createFromResource(this,
R.array.Counties, android.R.layout.simple_spinner_item);
UScounties.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
Counties.setAdapter(UScounties);
Spinner Cities = (Spinner) findViewById(R.id.spinCity);
ArrayAdapter UScities = ArrayAdapter.createFromResource(this,
R.array.Cities,android.R.layout.simple_spinner_item);
UScities.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
Cities.setAdapter(UScities);
initialize();
bNext.setOnClickListener(this);
}
What code should i use and where?PS. whoever may answer could u use my exact variables so i won't be confused,Thanks in Advance.
countries.setOnItemSelectedListener(new OnItemSelectedListener() {
ArrayAdapter<String> stateadapter=null;
#Override
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id) {
switch (pos) {
case 0:
stateadapter = new ArrayAdapter<String>(
activityclass.this,
android.R.layout.simple_spinner_item, Arrays
.asList(getResources().getStringArray(
R.array.USAstate)));
states.setAdapter(stateadapter);
case 1:
stateadapter = new ArrayAdapter<String>(
activityclass.this,
android.R.layout.simple_spinner_item, Arrays
.asList(getResources().getStringArray(
R.array.Indiastate)));
states.setAdapter(stateadapter);
}
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
}
Select State
<string-array name="USAstate">
<item>california</item>
<item>texas</item>
<item>virgina</item>
<item>alaska</item>
</string-array>