I have an Activity with a ViewPager containing multiple fragments. How can I now access a TextView in one of that fragments to change its text from the main activity? I tried multiple ways and they all ended with errors
this is My headerAdapter
public class HeaderAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments;
public HeaderAdapter(FragmentManager fm,List<Fragment> fragments) {
super(fm);
this.fragments=fragments;
}
#Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
#Override
public int getCount() {
return this.fragments.size();
}
And my header.xml contains an imageview and a text view like this:
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/fj"
android:textColor="#ff0000"
android:textSize="100dp"
android:text="aaa"
/>
<ImageView
android:alpha="0.7"
android:layout_width="wrap_content"
android:layout_height="203dp"
android:id="#+id/head1"
android:scaleType="fitXY"
android:src="#drawable/dash_widget_0"/>
</RelativeLayout>
My view pager like this:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="1">
<android.support.v4.view.ViewPager
android:layout_width="wrap_content"
android:layout_height="203dp"
android:id="#+id/header_pager"
>
</android.support.v4.view.ViewPager>
in mainActivity I need to change the textView?
You shouldn't access the textview from activity. That would be very hard to understand later and also that would cause total mess in your code.
What you should do is to implement public methods that do the work inside of a fragment. Accessing this method can be done in a super easy way by calling (YOUR_FRAGMENT_TYPE)HeaderAdapter#getItem(index). To avoid exceptions in casting the types check the Fragment with instanceOf.
Even though their might be a better way to implement what you are doing. You can get a reference to your Fragment from a view pager using this method
private Fragment getFragmentFromPager(int index) {
return getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.header_pager + ":" + index);
}
Just keep a public reference to your TextView inside the Fragment so you can access it.
Related
Hello I have a problem with setting the visibility of the cardView part.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout(..........)>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
(..........)>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/titleLayout"
(..........)>
<TextView
android:id="#+id/text_view_title"
(..........)/>
<androidx.constraintlayout.widget.ConstraintLayout
android:visibility="gone" <<<<<<<<<
android:id="#+id/expandableView"
(..........)>
<TextView
android:id="#+id/text_view_description"
(..........) />
<TextView
android:id="#+id/text_view_priority"
(..........) />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
How you can see I divided the cardView into two parts. In my showDescription() method I want to change the visibility of description section to visible or (if it's already visible) to gone.
View cardView = inflater.inflate(R.layout.note_item, container, false);
final ConstraintLayout expandableView = cardView.findViewById(R.id.expandableView);
adapter.setOnItemClickListener(new NoteAdapter.OnItemClickListener() {
#Override
public void onItemClick(final DocumentSnapshot documentSnapshot, int position) {
Note note = documentSnapshot.toObject(Note.class);
int pathInt = position;
String path =String.valueOf(pathInt);
showDescription(expandableView);
}
});
return RootView;
}
public void showDescription (ConstraintLayout expandableView){
if(expandableView.getVisibility()== View.VISIBLE){
expandableView.setVisibility(View.GONE);
}else {
expandableView.setVisibility(View.GONE);
}
}
}
I don't know why but after click on cardView (no matter which one) nothing happens. Maybe it's since my app don't know on witch cardView execute that method ? How I can make it works ?
The problem is here:
final ConstraintLayout expandableView = cardView.findViewById(R.id.expandableView);
You are making your expandableView final. final variable can not be modified. Remove the final keyword:
ConstraintLayout expandableView = cardView.findViewById(R.id.expandableView);
I think also you should place your showDescription function's code inside setOnItemClickListener instead of passing `expandableView' to a function.
I have a page in which I'm taking the START TIME and END TIME from DATABASE.
Let's say the START TIME is 7:00 and END TIME is 22:00
I want to use this START TIME and END TIME to show in my page as textview like 7:00 8:00 9:00 and sooo on till 22:00 as textview
Also I have an imageview that will also increase when the text increases.
How can I achieve this?
Also I want the result text in Horizontal Scroll View with Imageview at top and text view as bottom of each imageview
char first = StartTime.charAt(0);
int StartTimeint = Integer.parseInt(String.valueOf(first));
int l;
for( l = StartTimeint; l<=22; l++){
Log.d("SeatsPage", "Time is "+l);
}
timeofseats.setText(Integer.toString(l));
This is I have done so far but I'm getting 23 as a result, the textview is not increasing
This is my XML File
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:id="#+id/llMain"
android:layout_height="match_parent"
tools:context=".SeatsPagewithDB.SeatsPage">
<ImageView
android:id="#+id/imageView11"
android:layout_width="150px"
android:layout_height="150px"
android:layout_marginStart="28dp"
android:layout_marginEnd="326dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/seat" />
<TextView
android:id="#+id/timeofseats"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="334dp"
android:background="#FF0000"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="7:00"
android:textColor="#fff"
android:textSize="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/imageView11" />
</android.support.constraint.ConstraintLayout>
This is the result I am getting as layout
This what I want programmatically
The XML code that you write in your layout.xml file to create the UI is for static UI only. What you are asking is to create views dynamically during runtime. Although you can definitely create views using java code on a click of a button or something. But it is better to code less for the UI whenever possible and keep it separated from the program code. Instead use the tools given to us by the framework we are using.
In Android those tools include stuff like ListView, GridView and the newer and better RecyclerView. These views help you add other views dynamically to your UI in runtime. You define one of them or more (depending on your UI needs) once in your layout.xml and configure them using java code like any other view.
This is how you can use RecyclerView to achieve your goal. I can't explain everything how RecyclerView works and what each line of code does as it will make a very long post but I have tried to highlight main things briefly.
1. Add RecyclerView in your layout file.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
2. Create another layout file and define the template UI of the item that the RecyclerView is going to display. RecyclerView will populate each item that it holds with this layout.
item_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="#+id/imageView_alarm"
android:layout_width="90dp"
android:layout_height="90dp"
android:src="#drawable/alarm" />
<TextView
android:id="#+id/textView_Time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:background="#FF0000"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:text="Time"
android:textColor="#android:color/background_light"
android:textSize="24sp" />
</LinearLayout>
3. Create a ViewHolder class that extends from RecyclerView.ViewHolder. View holder is a RecyclerView related concept. In short it works as a wrapper around the view of a single item and aids in binding new data to the view of the item. Create a bind() function inside view holder to make your life easier.
EDIT: I have updated the class by implementing the View.OnClickListener interface, modified the constructor to pass in the context from onCreateViewHolder() and adding a setItemPosition() just for the sake to pass the item position number from onBindViewHolder() all over to here so we can use this position number in our onClick() method of the interface
MyViewHolder.java [UPDATED]
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView textView;
private int itemPosition;
private Context mContext;
public MyViewHolder(#NonNull View itemView, Context context) {
super(itemView);
itemView.setOnClickListener(this);
mContext = context;
textView = itemView.findViewById(R.id.textView_Time);
}
void bind(String timeText)
{
textView.setText(timeText);
}
void setItemPosition(int position)
{
itemPosition = position;
}
#Override
public void onClick(View v) {
Toast.makeText(mContext, "You clicked item number: " + itemPosition , Toast.LENGTH_SHORT).show();
}
}
4. Create an Adapter class that extends from RecyclerView.Adapter. Adapter works as a bridge between the UI data and RecyclerView itself. An Adapter tells the RecyclerView what layout file to inflate and how many to inflate. RecyclerView job is to deal with how to inflate it on the UI.
EDIT : Just changed myViewHolder in onCreateViewHolder() to match the modified constructor of MyViewHolder. Added the call to setItemPosition() in the onBindViewHolder().
MyAdapter.java [UPDATED]
public class MyAdapter extends RecyclerView.Adapter {
List<String> timeIntervalList = new ArrayList<>();
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view, parent, false);
MyViewHolder myViewHolder = new MyViewHolder(view , parent.getContext());
return myViewHolder;
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
MyViewHolder viewHolder = (MyViewHolder) holder;
viewHolder.setItemPosition(position);
viewHolder.bind(timeIntervalList.get(position));
}
#Override
public int getItemCount() {
return timeIntervalList.size();
}
public void addItem (String timeText)
{
timeIntervalList.add(timeText);
notifyItemInserted(getItemCount());
}
}
In this adapter you will see two functions. OnCreateViewHolder() inflates the view using the template layout file for a single item and OnBindViewHolder() binds new data to the default values of the of the view just created. The data used for binding is stored in a list inside this Adapter called the timeIntervalList. This list will hold your time interval strings so they can be updated on the view.
5. Finally, use this RecyclerView where you want to use it. Like in your MainActivity.java. RecyclerView needs to be told in what fashion to display the items (e.g list , grid etc ) using a LayoutManager. LinearLayoutManager will display items either vertically or horizontally. You can see I am using your logic to increment time from string and adding new views to RecyclerView using the addItem() function of the MyAdapter class.
MainActivity.java
public class MainActivity extends AppCompatActivity {
private RecyclerView myRecyclerView;
private MyAdapter myAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myRecyclerView = findViewById(R.id.recyclerView);
myAdapter = new MyAdapter();
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this , LinearLayoutManager.HORIZONTAL, false);
myRecyclerView.setLayoutManager(linearLayoutManager);
myRecyclerView.setAdapter(myAdapter);
// This is how you will populate the recycler view
String START_TIME = "7:00";
String END_TIME = "22:00";
char first = START_TIME.charAt(0);
int StartTimeint = Integer.parseInt(String.valueOf(first));
int l;
for( l = StartTimeint; l<=22; l++){
// This is where new item are added to recyclerView.
myAdapter.addItem(l + ":00");
}
}
}
This is the final result.
Change your activity layout XML code as follows,
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:id="#+id/llMain"
android:layout_height="match_parent"
tools:context=".SeatsPagewithDB.SeatsPage">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
...
...>
<LinearLayout
android:id="#+id/container"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</HorizontalScrollView>
</android.support.constraint.ConstraintLayout>
Move the textview and imageview to another XML file let's call it item_view.xml (you can name it whatever you wish). we are doing so because the root view of this file will be reused.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/imageView11"
android:layout_width="150px"
android:layout_height="150px"
app:srcCompat="#drawable/seat"/>
<TextView
android:id="#+id/timeofseats"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF0000"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="7:00"
android:textColor="#fff"
android:textSize="20dp"/>
</LinearLayout>
Now make following changes in your Java file
LinearLayout container = findViewById(R.id.container); // or rootView.findViewById() for custom View and Fragment
char first = StartTime.charAt(0);
int StartTimeint = Integer.parseInt(String.valueOf(first));
for(int l = StartTimeint; l<=22; l++){
Log.d("SeatsPage", "Time is "+l);
View view = LayoutInflater.from(container.getContext()).inflate(R.layout.item_view, null);
TextView timeofseats = view.findViewById(R.id.timeofseats);
timeofseats.setText(Integer.toString(l));
container.addView(view);
}
I have a Recycler View in ItemActivity and its Adapter as a seperate class ItemAdapter.Now based on the count of the Item chosen i need to update the text on a button placed in ItemActivity.How can it be done?
note:I have passed getApplicationContext() as the context to the Adapter.It passes the GlobalValue context which I have set in the manifest.
<application
android:name=".GlobalValues"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:theme="#style/AppTheme">
The following is my ItemActivity.xaml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="5dp"
tools:context=".ItemPickerActivity">
<TextView
android:id="#+id/itemstext"
android:layout_marginTop="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Choose Items"
android:fontFamily="#font/exo_semibold"
android:textColor="#color/dark_grey"
/>
<android.support.v7.widget.RecyclerView
android:layout_marginHorizontal="3dp"
android:id="#+id/pickerRecview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/itemstext"
android:layout_marginTop="7dp" />
<RelativeLayout
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="50dp"
android:padding="10dp"
android:id="#+id/checkout"
android:clickable="true"
android:background="#color/go_green"
>
<TextView
android:id="#+id/Total"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Rs XXX"
android:layout_marginLeft="5dp"
android:textSize="18sp"
android:textColor="#color/white"
android:layout_centerVertical="true"
android:fontFamily="#font/exo_semibold"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Checkout"
android:textColor="#color/white"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:textSize="22sp"
android:fontFamily="#font/exo_semibold"
/>
<TextView
android:id="#+id/TotalItems"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="5dp"
android:text="xx Items"
android:fontFamily="#font/exo_semibold"
android:textColor="#color/white"
android:textSize="18sp" />
</RelativeLayout>
</RelativeLayout>
And this is how i instantiate the adapter object
ItemPickerAdapter adapter = new ItemPickerAdapter(getApplicationContext(), ItemsList);
recyclerView.setAdapter(adapter);
I need to change the value of ItemCount in my ItemActitvity from the adapter!Please advise me on how it is possible.Thanks!
The easiest way would be to make the Adapter class an inner class contained within the Activity class. Then make the View you need to manipulate a global variable.
You can do the following
Create one interface
public interface ItemCountListner {
void onItemCountUpdate(int count);
}
Implement interface in your activity and pass the reference to your adapter
class MainActivity implements ItemCountListner {
---------
ItemPickerAdapter adapter = new ItemPickerAdapter(MainActivity.this, ItemsList, this);
---------
//implemented method
void onItemCountUpdate(int count){
// update your ui
}
}
Add argument in your adapter constructor
public ItemPickerAdapter(Context context, List itemList,
ItemCountListner listener)
Update your ui by calling
listener.onItemCountUpdate(count);
Inside your RecyclerView Adapter, you can define your own viewModel and inside that, you can attach onClick on any component you want. For eg:
public class MyViewHolder extends RecyclerView.ViewHolder
{
private TextView eachFeaturesName;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
eachFeaturesName = itemView.findViewById(R.id.eachFeaturesName);
}
}
And inside onBindViewHolder function , you can do this:
public void onBindViewHolder(#NonNull final MyViewHolder myViewHolder, final int position) {
//myViewHolder.eachFeaturesName.setonViewClickListener(...)
}
This is an easy way to use onClickListener on RecyclerView
Change the adapter instantiation in your activity from:
ItemPickerAdapter adapter = new ItemPickerAdapter(getApplicationContext(), ItemsList);
to this:
ItemPickerAdapter adapter = new ItemPickerAdapter(this, ItemsList);
meaning you pass the activity's context and not the application's context.
Then in your adapter class declare this:
MainActivity mainActivity = (MainActivity) context;
replace MainActivity with your activity's class name and context with the name of the parameter of your adapter class constructor for the Context.
Now you can access every public method, property, view in your activity by:
mainActivity.something
Edit1: Use a variable in your activity class
Context mainContext = this;
then instantiate the adapter:
ItemPickerAdapter adapter = new ItemPickerAdapter(mainContext, ItemsList);
Edit2: If you want to access your activity's UI elements like a TextView from your adapter, create a public method inside the activity class:
public void setTextViewText(String text) {
myTextView.setText(text);
}
and call it from the adapter:
mainActivity.setTextViewText("some text");
I am aware that other people have asked this question, but I have looked at other solutions and still can't get it to work.
Adapter code:
private class CustomTextAndImageAdapter extends ArrayAdapter<String> {
private Context context;
private Activity activity;
private ArrayList<String> timeArrayList;
private ArrayList<Bitmap> weatherIconArrayList;
private ArrayList<String> descriptionArrayList;
private ArrayList<String> tempArrayList;
private ArrayList<String> popArrayList;
private ArrayList<String> windSpeedArrayList;
public final void setTimeArrayList(ArrayList<String> timeArrayList)
{
this.timeArrayList = timeArrayList;
}
public final void setDescriptionArrayList(ArrayList<String> descriptionArrayList)
{
this.descriptionArrayList = descriptionArrayList;
}
public final void setTempArrayList(ArrayList<String> tempArrayList)
{
this.tempArrayList = tempArrayList;
}
public final void setPopArrayList(ArrayList<String> popArrayList)
{
this.popArrayList = popArrayList;
}
public final void setWindSpeedArrayList(ArrayList<String> windSpeedArrayList)
{
this.windSpeedArrayList = windSpeedArrayList;
}
public final void setWeatherIconArrayList(ArrayList<Bitmap> weatherIconArrayList)
{
this.weatherIconArrayList = weatherIconArrayList;
}
public CustomTextAndImageAdapter(Context context, Activity activity, int resource)
{
super(context, resource);
this.context = context;
this.activity = activity;
}
#Override
public View getView(int position, View view, ViewGroup parent)
{
Log.d(Constants.LOG_TAG, "getView() method called");
LayoutInflater inflater = activity.getLayoutInflater();
View rowView= inflater.inflate(R.layout.itemlistrow, null, false);
TextView timeTextView = (TextView)rowView.findViewById(R.id.time);
timeTextView.setText(timeArrayList.get(position));
Log.d(Constants.LOG_TAG, "Time text view text = " + timeArrayList.get(position));
ImageView iconImageView = (ImageView) rowView.findViewById(R.id.weatherIcon);
iconImageView.setImageBitmap(weatherIconArrayList.get(position));
TextView descriptionTextView = (TextView)rowView.findViewById(R.id.description);
descriptionTextView.setText(descriptionArrayList.get(position));
TextView tempTextView = (TextView)rowView.findViewById(R.id.temp);
tempTextView.setText(tempArrayList.get(position));
TextView popTextView = (TextView)rowView.findViewById(R.id.pop);
popTextView.setText(popArrayList.get(position));
TextView windSpeedTextView = (TextView)rowView.findViewById(R.id.windSpeed);
windSpeedTextView.setText(windSpeedArrayList.get(position));
return rowView;
}
}
List item layout (itemlistrow.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="1">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/time" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/weatherIcon"
/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Sunny"
android:id="#+id/description"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="11 C"
android:id="#+id/temp"
/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text = "Rain:"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text = "Wind:"
/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id = "#+id/pop"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text = "#+id/windSpeed"
/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
In some of the other solutions, it mentions overriding getCount(). Is this what I am doing wrong? If so, how would I know what to put in for getCount(), as there are multiple different ArrayLists used. Is it a case of picking one of them, as they are all the same length, e.g. timeArrayList.size()?
Using multiple ArrayList objects like that kind of defeats the purpose of using an ArrayAdapter, whose idea is to have a single source of items. Not to mention that the code right now doesn't look nice at all.
I'd suggest to first create a Weather object that will hold your data:
public class Weather {
private String time;
private Bitmap weatherIcon;
private String description;
private String temp;
private String pop;
private String windSpeed;
// build object here, provide getters, etc....
.....
}
Than your adapter can be transformed to something simpler like this:
private class CustomTextAndImageAdapter extends ArrayAdapter<Weather>
{
private LayoutInflater inflater;
public CustomTextAndImageAdapter(Context context, Activity activity, int resource, List<Weather> items)
{
super(context, resource, items);
this.inflater = LayoutInflater.from(context);
}
#Override
public View getView(int position, View view, ViewGroup parent)
{
View rowView= inflater.inflate(R.layout.itemlistrow, null, false);
TextView timeTextView = (TextView)rowView.findViewById(R.id.time);
timeTextView.setText(getItem(position).getTime());
ImageView iconImageView = (ImageView) rowView.findViewById(R.id.weatherIcon);
iconImageView.setImageBitmap(getItem(position).getWeatherIcon());
........
return rowView;
}
}
Main difference is that it's now an ArrayAdapter<Weather> and that you're passing the arguments directly in the constructor of the adapter. Users of the adapter now have to call just 1 constructor, instead of all the final methods that had to be called before.
The other major difference is that you're passing the items list to the super class. Now your adapter knows it's size (internally getCount() will be == items.size()) so getView() will be called appropriately.
As a final thought - the adapter is still not using the ViewHolder pattern, which you should totally implement! There's been numerous posts for it, so just search a bit and you'll find it.
This is not a good way to populate a ListView using an adapter which populates the data from multiple ArrayList. Generally we use a single source of dataset to be passed to an adapter in case of showing a list in Android.
So in your case, when you'll call the notifyDatasetChanged it shouldn't take effect in the list properly as far as I can guess.
notifyDatasetChanged basically calls the getCount function of the adapter and checks if the size of the ArrayList associated with the adapter is changed or not. If the size of the ArrayList is changed, it refreshes the ListView and the getView function gets called.
In your case, I don't see any getCount function though. getCount usually returns the size of the ArrayList associated with the adapter.
So I would suggest, using a single ArrayList to be passed to the adapter. You can merge multiple ArrayList and can use one joined HashMap in your case too. Its your decision, exactly how you can pass a single list of your dataset to the adapter to populate them into a ListView.
I have a main activity (ActivityMain.java) that I would like to use to navigate between four fragments. In one of these fragments, I'm attempting to place a CardView in conjunction with a RecyclerView to create a vertical list of cards. However, so far I've been unable to get any of the cards to display when I run the app. The CardView will display perfectly in Android Studio's design preview, but when an actual device/emulator is used it disappears.
I've tried to manually set the visibility of the CardView through Java, but it continued to stay invisible. I believe that the fragment's layout could be covering the CardView's layout, but I'm still very new to Android development so I'm not completely sure what the problem could be.
Below I've pasted the classes and XML files that are likely to be associated with my problem.
AdapterMainFeed.java
public class AdapterMainFeed extends RecyclerView.Adapter<AdapterMainFeed.ViewHolderMainFeed> {
private ArrayList<Article> listArticlesMain = new ArrayList<>();
private LayoutInflater inflater;
public AdapterMainFeed(Context context) {
inflater = LayoutInflater.from(context);
}
public void setArticlesMain(ArrayList<Article> listArticlesMain) {
this.listArticlesMain = listArticlesMain;
notifyDataSetChanged();
}
#Override
public ViewHolderMainFeed onCreateViewHolder(ViewGroup container, int i) {
View layout = inflater.inflate(R.layout.view_main_feed, container, false);
Article article1 = new Article("asdf", "ghj", "klm", new Date(0));
Article article2 = new Article("sdfg", "hjk", "lmn", new Date(0));
Article article3 = new Article("dfgh", "jkl", "mno", new Date(0));
listArticlesMain.add(article1);
listArticlesMain.add(article2);
listArticlesMain.add(article3);
return new ViewHolderMainFeed(layout);
}
#Override
public void onBindViewHolder(ViewHolderMainFeed viewHolderMainFeed, int i) {
Article currentArticle = listArticlesMain.get(i);
viewHolderMainFeed.articleTitle.setText(currentArticle.getTitle());
viewHolderMainFeed.articleAuthor.setText(currentArticle.getAuthor());
viewHolderMainFeed.articleWebsite.setText(currentArticle.getWebsite());
DateFormat formatter = DateFormat.getDateTimeInstance();
final String timePosted = formatter.format(currentArticle.getTimePosted());
viewHolderMainFeed.articleTime.setText(timePosted);
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
#Override
public int getItemCount() {
return listArticlesMain.size();
}
static class ViewHolderMainFeed extends RecyclerView.ViewHolder {
TextView articleTitle;
TextView articleAuthor;
TextView articleWebsite;
TextView articleTime;
public ViewHolderMainFeed(View itemView) {
super(itemView);
articleTitle = (TextView) itemView.findViewById(R.id.mainArticleTitle);
articleAuthor = (TextView) itemView.findViewById(R.id.mainArticleAuthor);
articleWebsite = (TextView) itemView.findViewById(R.id.mainArticleWebsite);
articleTime = (TextView) itemView.findViewById(R.id.mainArticleTime);
}
}
}
view_main_feed.xml
<?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:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp"
tools:context="com.convergeapp.converge.ActivityMain">
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
card_view:cardCornerRadius="7dp"
card_view:cardBackgroundColor="#color/colorPurpleSeance"
android:id="#+id/mainArticleCard"
android:layout_width="match_parent"
android:layout_height="300dp"
android:padding="8dp"
android:clickable="true">
<RelativeLayout
android:id="#+id/mainArticleLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<TextView
android:id="#+id/mainArticleTitle"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"/>
<TextView
android:id="#+id/mainArticleAuthor"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_below="#id/mainArticleTitle"/>
<TextView
android:id="#+id/mainArticleWebsite"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_below="#+id/mainArticleTime"/>
<TextView
android:id="#+id/mainArticleTime"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
After playing around with some changes, I finally discovered the solution. What I did was add the Article objects to the list in the main fragment's onCreateView method. Additionally, I instantiated CardView in the ViewHolder, though that didn't help me see the cards initially.
So, if you're ever in a similar predicament and can't figure out the solution, try to actually create the objects before setting them.
You need to call notifyDataSetChanged(); inside onCreateViewHolder after adding the new articles so that the itemcount is updated