I have a fragment which is using a Relative layout. Within that XML, I have two views - a TextView and a RecyclerView
There are no compilation errors, but the cards from the RecyclerView don't show up while running the app:
Here's the Fragment code:
package com.hfad.bitsandpizzas;
import android.content.Intent;
import android.os.Bundle;
import android.app.Fragment;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
public class TopFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
RelativeLayout layout = (RelativeLayout)inflater.inflate(R.layout.fragment_top, container, false);
RecyclerView pizzaRecycler = (RecyclerView)layout.findViewById(R.id.pizza_recycler);
String[] pizzaNames = new String[2];
for(int i=0; i<2; i++){
pizzaNames[i]=Pizza.pizzas[i].getName();
}
int[] pizzaImages = new int[2];
for(int i=0; i<2; i++){
pizzaImages[i]=Pizza.pizzas[i].getImageResourceId();
}
GridLayoutManager layoutManager = new GridLayoutManager(getActivity(),2);
pizzaRecycler.setLayoutManager(layoutManager);
CaptionedImagesAdapter adapter = new CaptionedImagesAdapter(pizzaNames, pizzaImages);
pizzaRecycler.setAdapter(adapter);
adapter.setListener(new CaptionedImagesAdapter.Listener() {
#Override
public void onClick(int position){
Intent intent = new Intent(getActivity(), PizzaDetailActivity.class);
intent.putExtra(PizzaDetailActivity.EXTRA_PIZZANO, position);
getActivity().startActivity(intent);
}
});
return layout;
}
}
Here is the layout XML:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/title_top"
android:id="#+id/top_text"/>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/pizza_recycler"
android:layout_below="#+id/top_text"
android:layout_marginTop="10dp"
android:scrollbars="vertical"/>
And here is the Adapter code:
package com.hfad.bitsandpizzas;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
public class CaptionedImagesAdapter extends RecyclerView.Adapter<CaptionedImagesAdapter.ViewHolder> {
private String[] captions;
private int[] imageIds;
private Listener listener;
public CaptionedImagesAdapter(String[] captions, int[] imageIds){
this.captions = captions;
this.imageIds = imageIds;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
private CardView cardView;
public ViewHolder(CardView v){
super(v);
cardView=v;
}
}
#Override
public CaptionedImagesAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
CardView cv = (CardView) LayoutInflater.from(parent.getContext()).inflate(R.layout.card_captioned_image, parent, false);
return new ViewHolder(cv);
}
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
CardView cardView = holder.cardView;
ImageView imageView = (ImageView)cardView.findViewById(R.id.info_image);
Drawable drawable = cardView.getResources().getDrawable(imageIds[position]);
imageView.setImageDrawable(drawable);
imageView.setContentDescription(captions[position]);
TextView textView = (TextView)cardView.findViewById(R.id.info_text);
textView.setText(captions[position]);
cardView.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if(listener!=null){
listener.onClick(position);
}
}
});
}
#Override
public int getItemCount() {
return captions.length;
}
public static interface Listener{
public void onClick(int position);
}
public void setListener(Listener listener){
this.listener=listener;
}
}
Thanks!
The TextView's height in your layout is set to "match_parent". The fragment is set to match_parent as well and since probably the activity is set the same way, this means that your TextView will occupy the whole screen.
I imported your code and with minimal changes to by-pass missing objects, I was able to reproduce the problem.
By changing the height for the TextView to be "wrap_content", you'll be making room for the RecyclerView.
Related
please help me to find out where is the trouble in my code, i tried to set onclick listener to delete the item from the database, howerver i does nothing, i checked the code again and again but i didn't find out where in the code that cause the problem.
please help me
thanks
The layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:padding="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_toLeftOf="#id/btn_delete">
<TextView
android:id="#+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Title"
android:textColor="#color/white"
android:textSize="20sp"
android:gravity="center"
android:padding="8dp"
/>
<TextView
android:id="#+id/tv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Content"
android:textSize="20sp"
android:gravity="start"
android:padding="10dp"
android:textColor="#color/white" />
</LinearLayout>
<Button
android:id="#+id/btn_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="delete"
android:backgroundTint="#color/transparent"
android:textColor="#color/white"
android:layout_alignParentEnd="true"
android:layout_marginEnd="40dp"
android:layout_alignParentRight="true"/>
</RelativeLayout>
the adapter
package com.haki.mysimplehakidiarynotes.adapters;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.haki.mysimplehakidiarynotes.InterfaceDeleteListener;
import com.haki.mysimplehakidiarynotes.objects.ItemsObject;
import com.haki.mysimplehakidiarynotes.R;
import java.util.ArrayList;
public class ItemsAdapter extends RecyclerView.Adapter<ItemsAdapter.ItemViewHolder>{
private Context mContext;
private ArrayList<ItemsObject> arrayList;
private InterfaceDeleteListener deleteListener;
public ItemsAdapter(Context mContext, InterfaceDeleteListener deleteListener) {
this.mContext = mContext;
this.deleteListener = deleteListener;
}
public void setData(ArrayList<ItemsObject> arrayList){
this.arrayList = arrayList;
notifyDataSetChanged();
}
#NonNull
#Override
public ItemViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).
inflate(R.layout.layout_items, parent, false);
return new ItemViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ItemViewHolder holder, int position) {
ItemsObject object =arrayList.get(position);
if (object==null){
return;
}
holder.txtTitle.setText(object.getTitle());
holder.txtContent.setText(object.getContent());
holder.btn_delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
deleteListener.onClickDeleteListen(object);
}
});
}
#Override
public int getItemCount() {
if (arrayList!=null){
return arrayList.size();
}
return 0;
}
public class ItemViewHolder extends RecyclerView.ViewHolder {
private TextView txtTitle;
private TextView txtContent;
private Button btn_delete;
public ItemViewHolder(#NonNull View itemView) {
super(itemView);
txtTitle =itemView.findViewById(R.id.tv_title);
txtContent =itemView.findViewById(R.id.tv_content);
btn_delete = itemView.findViewById(R.id.btn_delete);
}
}
}
the main
package com.haki.mysimplehakidiarynotes.fragments.diary_tabs;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.haki.mysimplehakidiarynotes.InterfaceDeleteListener;
import com.haki.mysimplehakidiarynotes.adapters.ItemsAdapter;
import com.haki.mysimplehakidiarynotes.databases.DiaryDatabase;
import com.haki.mysimplehakidiarynotes.objects.ItemsObject;
import com.haki.mysimplehakidiarynotes.R;
import java.util.ArrayList;
public class DiaryLogFragment extends Fragment implements InterfaceDeleteListener {
private RecyclerView recyclerView;
private ArrayList<ItemsObject> arrayList = new ArrayList<>();
private ItemsAdapter adapter;
public DiaryLogFragment() {
}
public static DiaryLogFragment newInstance() {
DiaryLogFragment fragment = new DiaryLogFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_diary_log, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView = view.findViewById(R.id.rcv_items);
//arrayList.add(new ItemsObject("thử nghiệm","nội dung thử nghiệm"));
arrayList = (ArrayList<ItemsObject>) DiaryDatabase.getInstance(getActivity()).userDAO().getAllData();
adapter = new ItemsAdapter(getActivity(), this::onClickDeleteListen);
adapter.setData(arrayList);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity()
,LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setAdapter(adapter);
}
#Override
public void onResume() {
super.onResume();
arrayList = (ArrayList<ItemsObject>) DiaryDatabase.getInstance(getActivity()).userDAO().getAllData();
adapter.setData(arrayList);
}
#Override
public void onClickDeleteListen(ItemsObject object) {
DiaryDatabase.getInstance(getActivity()).userDAO().delete(object);
arrayList = (ArrayList<ItemsObject>) DiaryDatabase.getInstance(getActivity()).userDAO().getAllData();
adapter.setData(arrayList);
}
}
the interface
package com.haki.mysimplehakidiarynotes;
import com.haki.mysimplehakidiarynotes.objects.ItemsObject;
public interface InterfaceDeleteListener {
void onClickDeleteListen(ItemsObject object);
}
the Dao
package com.haki.mysimplehakidiarynotes.databases;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import com.haki.mysimplehakidiarynotes.objects.ItemsObject;
import java.util.List;
#Dao
public interface DiaryDAO {
//Bước 1. Tạo insert vào cơ sở dữ liệu
#Insert
void insert(ItemsObject itemsObject);
#Query("SELECT * FROM user order by id DESC")
List<ItemsObject> getAllData();
#Delete
void delete(ItemsObject object);
}
i checked the code many times, however i didn't findout where is the cause that doen'st delete the item from the database
I am creating fragments inside Android Studio where one of my fragments calls an API and displays the listview with a custom listadapter. However, I have read many similar examples but none can determine why my listview is not appearing.
This is my News Fragment:
package com.example.firebasetestapplication;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TextView;
import com.example.firebasetestapplication.databinding.FragmentNewsBinding;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
/**
* A simple {#link Fragment} subclass.
* Use the {#link NewsFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class NewsFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private Handler mHandler = new Handler(Looper.getMainLooper());
ArrayList<News> newsArrayList = new ArrayList<>();
// FragmentNewsBinding binding;
// Context thiscontext;
public NewsFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment NewsFragment.
*/
// TODO: Rename and change types and number of parameters
public static NewsFragment newInstance(String param1, String param2) {
NewsFragment fragment = new NewsFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_news,container,false);
TextView textview = v.findViewById(R.id.textview);
ListView listview = v.findViewById(R.id.listview);
// thiscontext = container.getContext();
textview.setText("");
// textView.setText("Trying for the first time");
// Inflate the layout for this fragment
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://api.jsonbin.io/v3/b/636b51910e6a79321e444107")
.get()
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(#NonNull Call call, #NonNull IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(#NonNull Call call, #NonNull Response response) throws IOException {
if(response.isSuccessful()) {
String myResponse = response.body().string();
try {
JSONObject jsonObject = new JSONObject(myResponse);
JSONObject record = jsonObject.getJSONObject("record");
JSONArray club_news = record.getJSONArray("Club_News");
Gson gson = new Gson();
Type listType = new TypeToken<ArrayList<News>>(){}.getType();
List<News> total_News = gson.fromJson(club_news.toString(),listType);
for(News news : total_News) {
textview.append("Club: " + news.club + " " + news.description + "\n");
newsArrayList.add(news);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
});
ListAdapter listAdapter = new ListAdapter(getActivity(),newsArrayList);
listview.setAdapter(listAdapter); // line that breaks program
// mHandler.post(new Runnable() {
// #Override
// public void run() {
// ListAdapter listAdapter = new ListAdapter(getActivity(),newsArrayList);
// listview.setAdapter(listAdapter); // line that breaks program
// }
// });
// getActivity().runOnUiThread(new Runnable() {
// #Override
// public void run() {
// ListAdapter listAdapter = new ListAdapter(getActivity(),newsArrayList);
// listview.setAdapter(listAdapter); // line that breaks program
// }
// });
return v;
}
}
The OkHttpRequest successfully gets all the data and organized with Gson. This is my ListAdapter:
package com.example.firebasetestapplication;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.ArrayList;
public class ListAdapter extends ArrayAdapter<News> {
public ListAdapter(#NonNull Context context, ArrayList<News> newsArrayList) {
super(context,R.layout.custom_news_item,newsArrayList);
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View listItemView = convertView;
News news = getItem(position);
if(listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(R.layout.custom_news_item,parent,false);
}
ImageView club_logo = listItemView.findViewById(R.id.club_logo);
TextView club = listItemView.findViewById(R.id.club);
TextView club_description = listItemView.findViewById(R.id.club_description);
TextView title = listItemView.findViewById(R.id.title);
TextView description = listItemView.findViewById(R.id.description);
TextView time = listItemView.findViewById(R.id.time);
club_logo.setImageResource(R.drawable.frats_color); // Temporary
club.setText(news.getClub());
club_description.setText(news.getClub_description());
title.setText(news.getTitle());
description.setText(news.getDescription());
time.setText(news.getTime());
return listItemView;
}
}
And my News class Model:
package com.example.firebasetestapplication;
public class News {
String club;
String club_description;
String title;
String description;
String time;
public News(String club, String club_description, String title, String description, String time) {
this.club = club;
this.club_description = club_description;
this.title = title;
this.description = description;
this.time = time;
}
public String getClub() {return club;}
public String getClub_description() {return club_description;}
public String getTitle() {return title;}
public String getDescription() {return description;}
public String getTime() {return time;}
public void setClub(String club) {this.club = club;}
public void setClub_description(String club_description) {this.club_description = club_description;}
public void setTitle(String title) {this.title = title;}
public void setDescription(String description) {this.description = description;}
public void setTime(String time) {this.time = time;}
}
Finally, here is my custom_news item xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp">
<LinearLayout
android:id="#+id/first_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="3dp">
<ImageView
android:id="#+id/club_logo"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#drawable/frats_color"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:orientation="vertical">
<TextView
android:id="#+id/club"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:textSize="20sp"
android:textColor="#color/black"
android:textStyle="bold"
android:text="Frater Sodalis" />
<TextView
android:id="#+id/club_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Social Club at Abilene Christian University"
android:textStyle="italic"/>
</LinearLayout>
</LinearLayout>
<TextView
android:id="#+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:padding="15dp"
android:text="8:15pm" />
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/first_layout"
android:layout_marginTop="0dp"
android:layout_marginStart="10dp"
android:textSize="15sp"
android:textColor="#color/black"
android:textStyle="bold"
android:text="Haunted Forrest is now open! 6869 E North " />
<TextView
android:id="#+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/title"
android:layout_marginTop="10dp"
android:layout_marginStart="10dp"
android:layout_marginBottom="10dp"
android:textSize="15sp"
android:text="#string/HF_Example"/>
</RelativeLayout>
</LinearLayout>
and my fragment_news xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".NewsFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="#+id/textview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textStyle="bold"
android:text="News Fragment" />
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/listview"
tools:listitem="#layout/custom_news_item" />
</FrameLayout>
I know if looks like a lot, but I am pretty sure that the error lies around the ListAdapter or the News Fragment. I was looking into whether the getActivity() was passing the correct context for the Fragment or whether my listview.setAdapter(listAdapter); needs a RunOnUiThread somehow in a fragment.
I would very much appreciate it if someone could give me a hint on what's missing for my listview. I know I am pretty close. Thank you so much!
Just in case you are wondering, the Main Activity looks like this:
package com.example.firebasetestapplication;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.example.firebasetestapplication.databinding.ActivityMainBinding;
import com.firebase.ui.database.FirebaseListAdapter;
import com.firebase.ui.database.FirebaseListOptions;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
public class MainActivity extends AppCompatActivity {
private TextView greetings;
private Button logout;
//Firebase
FirebaseAuth mAuth = FirebaseAuth.getInstance();
private FirebaseListAdapter<ChatMessage> adapter;
private FirebaseUser user;
private FirebaseUser currentUser;
private DatabaseReference reference;
// Binding
ActivityMainBinding binding;
//Assets
private FloatingActionButton fab;
private String userID;
#SuppressLint("MissingInflatedId")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
replaceFragment(new HomeFragment());
//
binding.bottomNavigationView.setOnItemSelectedListener(item -> {
switch (item.getItemId()) {
case R.id.home:
replaceFragment(new HomeFragment());
case R.id.profile:
break;
case R.id.settings:
break;
case R.id.news:
// startActivity(new Intent(MainActivity.this, NewsActivity.class));
replaceFragment(new NewsFragment());
}
return true;
});
logout = findViewById(R.id.signOut);
// greetings = findViewById(R.id.greeting);
currentUser = mAuth.getCurrentUser();
// fab = findViewById(R.id.fab);
//
// fab.setOnClickListener(new View.OnClickListener() {
// #Override
// public void onClick(View view) {
// EditText input = findViewById(R.id.input);
// FirebaseDatabase.getInstance()
// .getReference()
// .push()
// .setValue(new ChatMessage(input.getText().toString(),
// FirebaseAuth.getInstance()
// .getCurrentUser()
// .getDisplayName())
// );
//
// // Clear the input
// input.setText("");
// }
// });
logout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FirebaseAuth.getInstance().signOut();
startActivity(new Intent(MainActivity.this, LoginActivity.class));
}
});
if (currentUser == null)
{
Intent intent
= new Intent(MainActivity.this,
LoginActivity.class);
startActivity(intent);
}
else
{
// displayChatMessages();
user = FirebaseAuth.getInstance().getCurrentUser();
reference = FirebaseDatabase.getInstance().getReference("Users");
userID = user.getUid();
reference.child(userID).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
User userChat = snapshot.getValue(User.class);
if(userChat != null) {
String fullname = userChat.fullName;
String email = userChat.email;
String age = userChat.age;
// greetings.setText("Welcome, " + fullname + "!");
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Toast.makeText(MainActivity.this, "Something did not go right!", Toast.LENGTH_SHORT).show();
}
});
}
}
private void replaceFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.frame_layout, fragment);
fragmentTransaction.commit();
}
}
Hi I'm working on a small application which sets a countdown. Now I want this countdown to be seen in front of a background inside a recyclerview. So in the end a user will have set multiple countdown timers and these will be displayed with backgrounds inside a recyclerview.
What I have made right now is far from perfect, but it's in the right direction of what I want it to be. The only problem I have right now is, because I'm working with a recyclerview, the view (including the text with the countdown) will be recycled. So if I scroll down, the countdown will be reset. I think that's the problem I'm having but I have no clue how to solve it. This is the most important code:
The activity the recyclerview is in:
package anotherChallenge.example.criminalactivity;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.widget.DatePicker;
import com.example.criminalactivity.R;
import java.text.DateFormat;
import java.util.Calendar;
public class Overview extends AppCompatActivity {
private int[] allImages = {
R.drawable.festive1_pictures,
R.drawable.festive2_pictures,
R.drawable.festive3_pictures,
R.drawable.festive4_pictures,
R.drawable.festive5_pictures,
R.drawable.ferrari_materialistic_pictures,
R.drawable.house_materialistic_pictures,
R.drawable.boat_materialistic_pictures,
R.drawable.rolex_materialistic_pictures,
R.drawable.private_jet_materialistic_pictures,
R.drawable.holiday1_pictures,
R.drawable.holiday2_pictures,
R.drawable.holiday3_pictures,
R.drawable.holiday4_pictures,
R.drawable.holiday5_pictures,
R.drawable.meet1_pictures,
R.drawable.meet2_pictures,
R.drawable.meet3_pictures,
R.drawable.meet4_pictures,
R.drawable.meet5_pictures,
R.drawable.other1_pictures,
R.drawable.other2_pictures,
R.drawable.other3_pictures,
R.drawable.other4_pictures,
R.drawable.other5_pictures,
};
private RecyclerView recyclerView2;
private DatePicker datePicker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_overview);
// textClock.setFormat12Hour(null);
// textClock.setFormat24Hour("EEE/MMM d/yyyy hh:mm:ss");
recyclerView2 = findViewById(R.id.recyclerview2);
datePicker = findViewById(R.id.datepicker);
Calendar calendar = Calendar.getInstance();
String currentDate = DateFormat.getDateInstance(DateFormat.FULL).format(calendar.getTime());
System.out.println(currentDate);
// String filledInDate = datePicker.getDayOfMonth() + "/" + datePicker.getMonth() + "/"+
// datePicker.getYear();
adapterForOverview adapter = new adapterForOverview(this, allImages);
recyclerView2.setAdapter(adapter);
recyclerView2.setLayoutManager(new LinearLayoutManager(this));
}
}
Adapter for the recyclerview:
package anotherChallenge.example.criminalactivity;
import android.content.Context;
import android.os.CountDownTimer;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;
import com.example.criminalactivity.R;
public class adapterForOverview extends RecyclerView.Adapter<adapterForOverview.MyViewHolder> {
AddItem addItem;
int[] images;
Context context;
CustomAdapterCardView customAdapterCardView;
public adapterForOverview(Context context, int[] images) {
this.context=context;
this.images=images;
addItem = new AddItem();
// customAdapterCardView = new CustomAdapterCardView(context,
customAdapterCardView.getArrayList());
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
// holder.cardView.setCardBackgroundColor(Color.parseColor("#696969"));
new CountDownTimer(30000,1000) {
#Override
public void onTick(long millisUntilFinished) {
holder.myTextview.setText("The title will be here \n" + millisUntilFinished/1000);
}
#Override
public void onFinish() {
holder.myTextview.setText("Achieved!");
}
}.start();
holder.myImage.setImageResource(images[position]);
// holder.myImage.setImageDrawable(addItem.getDrawable());
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(context);
View view = layoutInflater.inflate(R.layout.itemsinoverview,parent,false);
return new MyViewHolder(view);
}
#Override
public int getItemCount() {
return images.length;
}
public class MyViewHolder extends RecyclerView.ViewHolder{
CardView cardView;
ImageView myImage;
TextView myTextview;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
cardView = itemView.findViewById(R.id.cardview2);
myImage = itemView.findViewById(R.id.imageView);
myTextview = itemView.findViewById(R.id.textviewOfCountdown);
}
}
}
XML Code of the item inside the recyclerview:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<androidx.cardview.widget.CardView
android:id="#+id/cardview2"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginHorizontal="8dp"
android:layout_marginVertical="4dp"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/constraintlayout2"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/imageView"
android:scaleType="fitXY"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="#+id/textviewOfCountdown"
android:layout_width="match_parent"
android:layout_height="100dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:gravity="center"
android:textColor="#ffffff"
android:textSize="25sp"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
Explanation:
As you know android's recyclerView recycles its views and reuses its viewHolders by calling onBind each time to update the item's data. I noticed that in onBindViewHolder
you create a CountDownTimer every time any data is bound, so you end up with multiple timers updating the same ViewHolder.
Bad solution:
One solution would be to make the adapter's items non-recyclable, but that wouldn't be optimal and negates the recycling ability of the recyclerview.
Good Solution:
The solution is to keep a reference to your timer inside your viewHolder called MyViewHolder. Then in onBindViewHolder check if the timer has already been instantiated. If yes, then cancel the previous timer and afterwards create again a new timer. If not, then there's no need to cancel anything you just proceed to the creation of a new timer object for the first time.
public void onBindViewHolder(#NonNull MyViewHolder holder, final int position) {
if (holder.timer != null) {
holder.timer.cancel();
}
holder.timer = new CountDownTimer(30000, 1000) {
...
}.start();
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
...
CountDownTimer timer;
...
}
The problem is that you're creating a new timer every time a new view is bound. You want to keep the data the adapterr is going to display separate from the view that will display it. In this case, you could manage the countdown timer in an object that represents each item in the list. For example (pseudocode):
class MyItem {
val imageResource: Int
val timer: CountDownTimer
}
In the adapter, you hold a list of MyItem and instead of creating a brand new timer, you just set the current value of the existing timer (pseudocode):
public class adapterForOverview extends RecyclerView.Adapter<adapterForOverview.MyViewHolder> {
MyItem[] items;
Context context;
public adapterForOverview(Context context, MyItem[] items) {
this.context=context;
this.items=items;
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
timer = items[position].timer
if (timer.isFinished()) {
holder.myTextview.setText("The title will be here \n" + millisUntilFinished/1000);
} else {
holder.myTextview.setText("Achieved!");
}
}
#Override
public int getItemCount() {
return items.length;
}
Finally you would create the timer wherever you're currently initializing the images now. Instead of updating any views, the on tick and finished method just tell the adapter to refresh that specific item in the list, which will then rebind the current timer values (pseudocode):
for (int i = 0; i < allImages.length; i++) {
items[i] = new MyItem()
items[i].image = allImages[i]
items[i].timer = new CountDownTimer(30000,1000) {
#Override
public void onTick(long millisUntilFinished) {
adapter.notifyItemChanged(i)
}
#Override
public void onFinish() {
adapter.notifyItemChanged(i)
}
}.start();
}
Again, this is all pseudo code and won't compiler, but should give you an idea of how to structure your code to solve your problem.
this my code it just shows a button and when you press it, it sets the image world as the device wallpaper, if you need more details just ask, I'm new so I don't know what you need to be able to help me :)
package com.example.dailybible;
import androidx.appcompat.app.AppCompatActivity;
import android.app.WallpaperManager;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
setWallpaper();
}
} );
}
private void setWallpaper () {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.world);
WallpaperManager manager = WallpaperManager.getInstance(getApplicationContext());
try {
manager.setBitmap(bitmap);
Toast.makeText(this, "Wallpaper set!", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
}
}
}
Look at how easy to change an Image on the screen every 5 seconds:
XML file:
setTimeout(function () { alert("JavaScript"); }, 1000);
<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"
android:orientation="vertical">
<ImageView
android:id="#+id/yourImageViewID"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:srcCompat="#drawable/image"
android:scaleType="centerCrop"
android:contentDescription="#string/inspect"/>
MainActivity.java file:
I added image1,image2,image3 to "drawable" folder.
public class MainActivity extends AppCompatActivity {
ImageView wallpaper;
public static Integer[] mThumbIds = {
R.drawable.guardian,R.drawable.image1,R.drawable.image2,R.drawable.image3
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
wallpaper = findViewById(R.id.yourImageViewID);
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
int i=0;
public void run() {
wallpaper.setImageResource(mThumbIds[i]);
i++;
if(i>mThumbIds.length-1)
{
i=0;
}
handler.postDelayed(this, 5000); //for interval...
}
};
handler.postDelayed(runnable, 2000); //for initial delay..
I see your code has a button.
Here is a simple example of how to change the image with a button.
I have 2 spinners in my application.one(spinner 1) for selecting qualification and another(spinner2) is to show courses according to selected qualification in spinner 1.
how can I add items in spinner2 on the basis of item selected in spinner 1.
Try This Code:
Java Class
package com.example.spinnerexam;
import java.util.ArrayList;
import java.util.List;
import android.annotation.TargetApi;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class SpinnerExample extends Activity implements OnItemSelectedListener{
private Spinner qualificationSpinner, coursesSpinner;
ArrayAdapter<String> courseAdapter;
List<ArrayList<String>> allCoursesList;
CustomOnItemSelectedListener pCustomOnItemSelectedListener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
qualificationSpinner = (Spinner) findViewById(R.id.spinner1);
coursesSpinner = (Spinner) findViewById(R.id.spinner2);
List<String> qualificationList = new ArrayList<String>();
qualificationList.add("B.tech");
qualificationList.add("M.tech");
qualificationList.add("MCA");
ArrayList<String> cources_Btech = new ArrayList<String>();
cources_Btech.add("Btechcourse1");
cources_Btech.add("Btechcourse2");
cources_Btech.add("Btechcourse3");
ArrayList<String> cources_Mtech = new ArrayList<String>();
cources_Mtech.add("Mtechcourse1");
cources_Mtech.add("Mtechcourse2");
cources_Mtech.add("Mtechcourse3");
ArrayList<String> cources_MCA = new ArrayList<String>();
cources_MCA.add("MCAcourse1");
cources_MCA.add("MCAcourse2");
cources_MCA.add("MCAcourse3");
allCoursesList = new ArrayList<ArrayList<String>>();
allCoursesList.add(cources_Btech);
allCoursesList.add(cources_Mtech);
allCoursesList.add(cources_MCA);
ArrayAdapter<String> qualificationAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, qualificationList);
qualificationAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
qualificationSpinner.setAdapter(qualificationAdapter);
courseAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item);
courseAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
coursesSpinner.setAdapter(courseAdapter);
addListenerOnSpinnerItemSelection();
}
// Add spinner data
public void addListenerOnSpinnerItemSelection(){
qualificationSpinner.setOnItemSelectedListener(this);
coursesSpinner.setOnItemSelectedListener(this);
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
courseAdapter.clear();
courseAdapter.addAll(allCoursesList.get(pos));
courseAdapter.notifyDataSetChanged();
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
}
}
XML layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Spinner
android:id="#+id/spinner1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:prompt="#string/spinner_prompt" />
<Spinner
android:id="#+id/spinner2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:prompt="#string/spinner_prompt" />
</LinearLayout>