Need to set additional information in list view - android-layout

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!!

Related

Android studio room database - not returning values in onRestart() method

My app is a list of element names. Clicking one goes to another activity with more details, and an editText and button to change its name. When I go back to the list, I want it to have the new name if updated. My onCreate method has this code which populates it from the database perfectly (ignore the hardcoded size, its just simpler for debugging)
final String DATABASE_NAME = "element_db";
final AppDatabase appDatabase;
appDatabase = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, DATABASE_NAME).build();
ListView list = (ListView)findViewById(R.id.listView);
final String[] element = new String[3];
new Thread(new Runnable() {
#Override
public void run() {
List<Element> elements;
elements = appDatabase.elementDao().fetchElements(); // a dao query "select*from"
int size = elements.size();
for (int i = 0; i < size; i++){
element[i] = elements.get(i).getName();
}
}
}) .start();
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this, R.layout.activity_list_view, R.id.textView, element);
list.setAdapter(arrayAdapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent i = new Intent(MainActivity.this, itemdetail.class);
i.putExtra("pos", position);
startActivity(i);
}
});
To achieve an updated list when returning to this screen, I copied the above code into the onRestart method, but now the database does not return anything. If I just set the array that goes into the adapter to {"a", "a", "a"} the list populates fine. Any ideas why the database works onCreate but not onRestart?
I think you can use ViewModel and livedata to observe any database change

duplicate view upon data change?

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.

Best way to create buttons dynamically

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

How to work with ids and strings in pagerTabStrip

Super newbie question about accessing information in strings. I have chunked together an app that uses a fragmentpager and the PagerTabStrip.
It is supposed to display titles on the tab, but mine displays nothing...because I am a total newbie hacking his way through. I am so grateful for this community.
From my layout file that calls the content (and once I fix it the title--id#pager_header right?):
<android.support.v4.view.PagerTabStrip
android:id="#+id/pager_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:paddingBottom="4dp"
android:paddingTop="4dp"
android:textColor="#ffffff" />
My code that gets me the swipeable pages of content:
public class Poems extends FragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.contentpage);
/** Getting a reference to the ViewPager defined the layout file */
ViewPager pager = (ViewPager) findViewById(R.id.pager);
/** Getting fragment manager */
FragmentManager fm = getSupportFragmentManager();
/** Instantiating FragmentPagerAdapter */
MyFragmentPagerAdapter pagerAdapter = new MyFragmentPagerAdapter(fm);
/** Setting the pagerAdapter to the pager object */
pager.setAdapter(pagerAdapter);
}
}
My code that should get me the titles from the string reference file.
public class MyFragment extends Fragment{
int mCurrentPage;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/** Getting the arguments to the Bundle object */
Bundle data = getArguments();
/** Getting integer data of the key current_page from the bundle */
mCurrentPage = data.getInt("current_page", 0);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.myfragment_layout, container,false);
TextView tv = (TextView ) v.findViewById(R.id.tv);
tv.setMovementMethod(new ScrollingMovementMethod());
switch(mCurrentPage){
case 0:
tv.setText(" ");
break;
case 1:
tv.setText(R.string.content_1);
break;
case 2:
tv.setText(R.string.content_2);
break;
case 3:
tv.setText(R.string.content_3);
break;
}
return tv;
}
}
How do I get pager_header from this?
A sample relevant string is:
<string name="content_1">Welcome to this app!</string>
I am thinking that I need to better understand strings since I'm coming from more of a text content background.
How do I include in the stings.xml file the indicators that allow the app to reference the content associated with pageview so that I can have that show up in the tab? How I do make it so that the content shows "Welcome to this app" but the title in the tab shows "Home"?
I think as if each entry (page) is like a line in a database with one point of reference being the title, one being the content, one being a link or some other content. Each has its own id, right?
Thank you in advance for explaining this to a beginner.
You need to implement getPageTitle(int position) in MyFragmentPagerAdapter. The String that is returned from this method is used to set the title of the PagerTabStrip.
#Override
public CharSequence getPageTitle(int position) {
Log.v(TAG, "getPageTitle");
String tabTitle;
switch(position) {
case 0:
tabTitle = "Tab #0";
break;
case 1:
tabTitle = "Home";
break;
case 2:
tabTitle = "Tab #2";
break;
case 3:
tabTitle = "Tab #3";
break;
default:
tabTitle = "Default Tab Title";
break;
}
return tabTitle;
}
You can make this more dynamic by making the title and content arguments that you pass in using a Bundle by calling setArguments(Bundle args) on your MyFragments that you add to your ViewPager. In MyFragment in onCreateView() you can then set your content based on the passed in content String argument. Then in MyFragmentPagerAdapter you can get a reference to the Fragment at the position and pull get the title directly from MyFragment.

How to make A Spinner access the other Spinner?

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>

Resources