Problem with setting visibility of cardView in recyclerView - java

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.

Related

How to increase the number of text in Android programmatically

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

MapView in lite mode causes RecyclerView to not scroll correctly

I'm building a chat app in Android Studio with the abitily to send routes on a map. I've implemented this by using a RecyclerView and ViewHolders, which hold the necessary UI with MapViews in lite mode (map:liteMode="true"). Thing is, when I add a map UI element to the recyclerView and scroll to the end by using scrollToPosition(adapter.getItemCount() - 1), the scrolling has trouble following the views and is always slightly off, as seen on the screenshot
(https://i.postimg.cc/BvMzrHJL/Screenshot-20190526-005535.png).
Moreover, the keyboard gets confused about the height of the views as well when clicked (https://i.postimg.cc/Hs6BsHfR/Screenshot-20190526-011647.png).
I have tried switching lite mode off, but it makes the scrolling laggy and handling lifecycle events becomes an issue since my MapViews are in ViewHolders, not in Activities or Fragments, see official documentation:
Users of this class [MapView] must forward all the life cycle methods from the
Activity or Fragment containing this view to the corresponding ones in
this class.
I have also tried changing the height of the layout from android:layout_height="wrap_content" to android:layout_height="250dp", but that also didn't work at all.
Also, scrolling works just fine with Views containing only text or an empty RelativeLayout istead of MapView.
I used this sample from Google's developer documentation https://github.com/googlemaps/android-samples/blob/master/ApiDemos/java/app/src/main/java/com/example/mapdemo/LiteListDemoActivity.java
So here is my ViewHolder (one of two):
private class SentRouteViewHolder extends RecyclerView.ViewHolder implements OnMapReadyCallback
{
MapView sentMap;
TextView routeSentTime;
GoogleMap map;
public SentRouteViewHolder(#NonNull View itemView) {
super(itemView);
sentMap = itemView.findViewById(R.id.sent_map);
routeSentTime = itemView.findViewById(R.id.route_sent_time);
sentMap.onCreate(null);
sentMap.onResume();
sentMap.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
MapsInitializer.initialize(getApplicationContext());
map = googleMap;
setMapRoute();
}
void bind(Message message)
{
sentMap.setTag(message);
setMapRoute();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm");
routeSentTime.setText(simpleDateFormat.format(message.getTime()));
}
void setMapRoute()
{
if(map == null) return;
Message message = (Message) sentMap.getTag();
if(message==null) return;
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
}
}
And adding the item to the RecyclerView:
activeCollection.add(newMessage).addOnSuccessListener(documentReference -> {
documentReference.get().addOnSuccessListener(documentSnapshot -> {
adapter.addMessage(documentSnapshot);
adapter.notifyItemInserted(adapter.getItemCount());
chatReycler.scrollToPosition(adapter.getItemCount()-1);
});
});
The onBindViewHolder:
SentRouteViewHolder routeViewHolder = (SentRouteViewHolder) viewHolder;
routeViewHolder.bind(message);
The onCreateViewHolder:
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.route_sent,parent,false);
Log.v("measure",String.valueOf(v.getMeasuredHeight()));
return new SentRouteViewHolder(v);
RecyclerView configuration:
manager.setStackFromEnd(true);
chatReycler.setLayoutManager(manager);
chatReycler.setAdapter(adapter);
chatReycler.setHasFixedSize(false);
chatReycler.setRecyclerListener(viewHolder -> {
if(viewHolder.getItemViewType()==ChatRecyclerViewAdapter.VIEW_TYPE_ROUTE_RECEIVED)
{
ChatRecyclerViewAdapter.ReceivedRouteViewHolder holder = (ChatRecyclerViewAdapter.ReceivedRouteViewHolder) viewHolder;
if(holder.map!=null)
{
holder.map.clear();
holder.map.setMapType(GoogleMap.MAP_TYPE_NONE);
}
}
else if (viewHolder.getItemViewType()==ChatRecyclerViewAdapter.VIEW_TYPE_ROUTE_SENT)
{
ChatRecyclerViewAdapter.SentRouteViewHolder holder = (ChatRecyclerViewAdapter.SentRouteViewHolder) viewHolder;
if(holder.map!=null)
{
holder.map.clear();
holder.map.setMapType(GoogleMap.MAP_TYPE_NONE);
}
}
});
The ViewHolder 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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:paddingBottom="3dp"
android:layout_marginBottom="13dp">
<ImageView
android:id="#+id/route_received_background"
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_marginStart="15dp"
android:src="#drawable/message_received_background"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.gms.maps.MapView
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="#+id/received_map"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="9dp"
app:layout_constraintBottom_toBottomOf="#+id/route_received_background"
app:layout_constraintEnd_toEndOf="#+id/route_received_background"
app:layout_constraintStart_toStartOf="#+id/route_received_background"
app:layout_constraintTop_toTopOf="#+id/route_received_background"
map:mapType="normal"
map:liteMode="true"
/>
<TextView
android:id="#+id/route_received_time"
style="#style/TextAppearance.MaterialComponents.Caption"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:textSize="13sp"
app:layout_constraintBottom_toBottomOf="#+id/route_received_background"
app:layout_constraintStart_toEndOf="#+id/route_received_background"
tools:text="11:50" />
</android.support.constraint.ConstraintLayout>
I want the RecyclerView to scroll to the bottom of the sent map, and not to the middle of it. How can I make that happen?
I had a similar problem with scrolling and checked that the parent layout was 0dp high. I changed it to match_parent and it worked.
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"

Inflated xml Layout with a TextView has an onClick attribute, but it does not get called.

I have an XML layout file that has a TextView within a CoordinatorLayout.
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".SpecificProgramSelectionActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="75dp"
android:id="#+id/saved_program"
android:text="Empty"
android:textAlignment="center"
android:gravity="fill"
android:textSize="20dp"
android:background="#drawable/program_selection_border"
android:textColor="#color/black"
android:clickable="true"
android:focusable="true"
android:onClick="addToSavedPrograms"
android:paddingTop="5dp"
android:paddingBottom="5dp"/>
And this code that inflates the layout and adds it into a Linear Layout in the activity's view.
for (PlayerWithObjectives player : players){
name = player.getName();
for (String objective : player.getObjectives()){
objectives.add(objective);
}
nameView = inflater.inflate(R.layout.inflatable_player_name_view, null);
((TextView)nameView.findViewById(R.id.saved_program)).setText(name);
((TextView)nameView.findViewById(R.id.saved_program)).setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
((TextView)nameView.findViewById(R.id.saved_program)).setTextSize(20);
linearLayout.addView(nameView);
}
(This is the activity's layout XML)
<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="match_parent"
android:layout_height="match_parent"
tools:context=".SpecificProgramSelectionActivity"
android:orientation="vertical">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="#+id/specific_program_selection_linear_layout">
</LinearLayout>
</ScrollView>
Everything looks fine in the app when I run it. Every inflated view shows up, the only issue is that the method that I specified in the onClick attribute for the inflated TextView does not get called. Why is that? Here is the method that is supposed to be called
public void addToSavedPrograms(View view){
String name = (String) (((TextView)view.findViewById(R.id.saved_program)).getText());
namesToSend.add(name);
editor.putStringSet("Tracked Players", namesToSend);
editor.commit();
Toast.makeText(getApplicationContext(),name + " was saved to preferences.", Toast.LENGTH_SHORT);
}
Why doesn't the method get called? I already saw all the other threads about using setContent() and stuff but that didn't work and it was not explained that great in the answer. Any help would be greatly appreciated.
public class YourActivity extends AppCompatActivity implements OnClickListener{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textview=(TextView)findViewById(R.id.saved_program);
textview.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch(view.getId()){
case R.id.saved_program:
//call your function here
default:
break;
}
}
you can do it like this.
Update:
First off, thank you to everybody that commented, your help was greatly appreciated. Your no judgment assistance is an awesome and welcome change from a lot of what I have experienced and seen on in this community.
Secondly, I figured out my issue. Or got my code to work at least. Once I got a better understanding of inflating layouts I changed this line of code
nameView = inflater.inflate(R.layout.inflatable_player_name_view, null);
To
nameView = (TextView) inflater.inflate(R.layout.inflatable_add_player_name_view, linearLayout, false);
The difference is that When you inflate, it returns an object that is the same type as the top parent in the specified layout file (Which in this case is "R.layout.inflatable_player_name_view"). So I changed nameView to a TextView object and cast the returned object as a TextView. Then I specified the wanted parent layout (To get the right layoutParams) and put false so that it does not attach it automatically to that parent layout. After that I simply made the alterations to the textView that I wanted, like setting the text values and whatnot, and then manually added it to the parent linearlayout that I wanted. After doing this there was not even a need to set an onClickListener programmatically because the android:onClick method worked just fine.

TextView in a viewpager

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.

CardView in fragment is invisible

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

Categories