Exchanging icons in listview items - java

I am trying to change icon image according to the item data . when pressing the icon, it should switch to other icon and change the item data. everything is going right but when i scroll up or down the new icon image change its place to some other items because i am using list view with adapter. how can i keep the new icons in the pressed items without mixing with other items.
package com.example.sairamkrishna.handymade;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
public class HandAdapter extends ArrayAdapter<HandClass> {
private int myColor;
public HandAdapter(Context context, ArrayList<HandClass> objects, int my_Color) {
super(context, 0, objects);
myColor = my_Color;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View myView = convertView;
final HandClass myData = getItem(position);
if (myView == null) {
myView = LayoutInflater.from(getContext()).inflate(
R.layout.label_item, parent, false);
}
ImageView aImage = (ImageView) myView.findViewById(R.id.itemImage);
aImage.setImageResource(myData.getClsImage());
TextView aName = (TextView) myView.findViewById(R.id.itemName);
aName.setText(myData.getClsName());
FrameLayout aColor = (FrameLayout) myView.findViewById(R.id.itemColor);
aColor.setBackgroundColor(myColor);
final ImageView aAddToBasket = (ImageView) myView.findViewById(R.id.itemAddToBasket);
aAddToBasket.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final Boolean aClsToBasket = (Boolean) myData.getClsToBasket();
if (aClsToBasket) {
aAddToBasket.setImageResource(R.drawable.ic_add_circle);
myData.setClsToBasket(false);
Toast.makeText(getContext(), "Remove from basket"+ position, Toast.LENGTH_SHORT).show();
} else {
// if (!aClsToBasket) {
aAddToBasket.setImageResource(R.drawable.ic_remove_circle);
myData.setClsToBasket(true);
Toast.makeText(getContext(), "Add to basket"+ position, Toast.LENGTH_SHORT).show();
}
}
});
ImageView aAddToFavorite = (ImageView) myView.findViewById(R.id.itemAddToFavorite);
aAddToFavorite.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getContext(), "Favorite - List item was clicked at " + position, Toast.LENGTH_SHORT).show();
}
});
return myView;
}
}

A fundamental concept of ListView and RecyclerView is that you need to "update" the value (in this case, the image) for each portion of the row every time getView() or onBindViewHolder() is called.
For example, every time getView() is called, you're always updating the (text) value of TextView aName. That is, there is always a call to aName.setText().
Right now, the only time you call aAddToBasket.setImageResource() is inside an OnClickListener. Of course, it makes sense to do it here, but you must also update the image outside of the listener.
Add this code right after your ImageView aAddToBasket line:
if ((Boolean) myData.getClsToBasket()) {
aAddToBasket.setImageResource(R.drawable.ic_remove_circle);
} else {
aAddToBasket.setImageResource(R.drawable.ic_add_circle);
}

Add this line after icon change.
adapter.notifyDataSetChanged();

Related

How to save items added in RecyclerView?

I have a RecyclerView but I face some problems. Whenever I add something to the recycler view and for example switch fragments or close the app all the items in the RecyclerView disappear. Would there be a way to save them? Any help would be nice!
Here is some code to see if anyone needs it:
Adapter
package com.example.freetrialtracker;
import android.content.Context;
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.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class SubTrialAdapter extends RecyclerView.Adapter<SubTrialAdapter.MyViewHolder>{
private ArrayList<SubTrial> listData;
private Context context;
private OnEditListener onEditListener;
public SubTrialAdapter(Context context, ArrayList<SubTrial> list,OnEditListener onEditListener){
this.listData=list;
this.context=context;
this.onEditListener=onEditListener;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View viewItem= LayoutInflater.from(parent.getContext()).inflate(R.layout.subscription_card_view,parent,false);
return new MyViewHolder(viewItem);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
SubTrial dataObj=listData.get(position);
holder.nameTxt.setText(dataObj.getNamee());
holder.startDate.setText(dataObj.getStartDate());
holder.endDate.setText(dataObj.getEndDate());
holder.description.setText(dataObj.getDescription());
holder.link.setText(dataObj.getLink());
holder.imgDelete.setOnClickListener(v->{
listData.remove(position);
notifyDataSetChanged();
});
holder.imgEdit.setOnClickListener(v->{
onEditListener.onEditClick(listData.get(position),position);
});
}
#Override
public int getItemCount() {
return listData.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView nameTxt,startDate,endDate,description,link;
ImageView imgEdit,imgDelete;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
nameTxt=itemView.findViewById(R.id.nameTxtId);
startDate=itemView.findViewById(R.id.startDateTxtId);
endDate = itemView.findViewById(R.id.endDateTxtId);
description = itemView.findViewById(R.id.descriptionId);
link = itemView.findViewById(R.id.linkId);
imgEdit=itemView.findViewById(R.id.imgEdit);
imgDelete=itemView.findViewById(R.id.imgDelete);
}
}
public void editData(SubTrial listDataObj,int currentPosition){
listData.get(currentPosition).setLink(listDataObj.getLink());
listData.get(currentPosition).setDescription(listDataObj.getDescription());
listData.get(currentPosition).setEndDate(listDataObj.getEndDate());
listData.get(currentPosition).setStartDate(listDataObj.getStartDate());
listData.get(currentPosition).setNamee(listDataObj.getNamee());
notifyDataSetChanged();
}
public interface OnEditListener{
void onEditClick(SubTrial listCurrentData, int CurrentPosition);
}
}
Fragment
import android.app.AlertDialog;
import android.os.Bundle;
import android.os.Parcelable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.ArrayList;
public class SubscriptionFragment extends Fragment implements SubscriptionDialogFragment.OnInputSelected {
AlertDialog alertDialog;
TextView textView1;
RecyclerView subscriptionList;
private FloatingActionButton mOpenDialog;
SubTrialAdapter subscriptionAdapterList;
ArrayList<SubTrial> subTrialArrayList;
#Override
public void sendInput(String name, String startDate, String endDate, String description, String link) {
addSubscription(name, startDate, endDate, description, link);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_subscription, container, false);
mOpenDialog = view.findViewById(R.id.fabSub);
subTrialArrayList = new ArrayList<>();
subscriptionList = view.findViewById(R.id.activityListSub);
subscriptionList.setHasFixedSize(true);
subscriptionList.setLayoutManager(new LinearLayoutManager(this.getActivity(), LinearLayoutManager.VERTICAL, false));
textView1 = view.findViewById(R.id.textView1);
mOpenDialog.setOnClickListener(v -> {
SubscriptionDialogFragment dialog = new SubscriptionDialogFragment();
dialog.setTargetFragment(SubscriptionFragment.this, 1);
dialog.show(getFragmentManager(), "Dialog");
});
return view;
}
public void addSubscription(String strName, String strStartDate, String strEndDate, String strDescription, String strLink) {
textView1.setText(strStartDate);
SubTrial obj = new SubTrial();
obj.setNamee(strName);
obj.setStartDate(strStartDate);
obj.setEndDate(strEndDate);
obj.setDescription(strDescription);
obj.setLink(strLink);
subTrialArrayList.add(obj);
subscriptionAdapterList = new SubTrialAdapter(this.getContext(), subTrialArrayList, this::onEditClick);
subscriptionList.setAdapter(subscriptionAdapterList);
}
private void onEditClick(SubTrial listCurrentData, int currentPosition) {
View view=LayoutInflater.from(this.getContext()).inflate(R.layout.edit_subscription,null);
AlertDialog.Builder builderObj=new AlertDialog.Builder(view.getContext());
EditText mSubscriptionName = view.findViewById(R.id.subscriptionName);
EditText mStartDate = view.findViewById(R.id.startDate);
EditText mEndDate = view.findViewById(R.id.endDate);
EditText mDescription = view.findViewById(R.id.description);
EditText mLink = view.findViewById(R.id.link);
MaterialButton btnEdit=view.findViewById(R.id.btnEdit);
mSubscriptionName.setText(listCurrentData.getNamee());
mStartDate.setText(listCurrentData.getStartDate());
mEndDate.setText(listCurrentData.getEndDate());
mDescription.setText(listCurrentData.getDescription());
mLink.setText(listCurrentData.getLink());
ImageView closeAlert = view.findViewById(R.id.closeAlert);
builderObj.setView(view);
builderObj.setCancelable(false);
closeAlert.setOnClickListener(v -> {
alertDialog.cancel();
});
btnEdit.setOnClickListener(v->{
String strName = "", strStartDate = "", strEndDate = "", strDescription = "", strLink = "";
if (mSubscriptionName.getText() != null) {
strName = mSubscriptionName.getText().toString();
}
if (strName.equals("")) {
Toast.makeText(this.getContext(), "Please enter Subscription Name", Toast.LENGTH_LONG).show();
return;
}
if (mStartDate.getText() != null) {
strStartDate = mStartDate.getText().toString();
}
if (strStartDate.equals("")) {
Toast.makeText(this.getContext(), "Please enter Start Date", Toast.LENGTH_LONG).show();
return;
}
if (mEndDate.getText() != null) {
strEndDate = mEndDate.getText().toString();
}
if (strEndDate.equals("")) {
Toast.makeText(this.getContext(), "Please enter End Date", Toast.LENGTH_LONG).show();
return;
}
if (mDescription.getText() != null) {
strDescription= mDescription.getText().toString();
}
if (strDescription.equals("")) {
Toast.makeText(this.getContext(), "Please enter Description", Toast.LENGTH_LONG).show();
return;
}
if (mLink.getText() != null) {
strLink = mLink.getText().toString();
}
if (strLink.equals("")) {
Toast.makeText(this.getContext(), "Please enter Link", Toast.LENGTH_LONG).show();
return;
}
editContact(strName, strStartDate, strEndDate, strDescription, strLink, currentPosition);
});
alertDialog=builderObj.create();
alertDialog.show();
}
public void editContact(String strUserName, String strStartDate, String strEndDate, String strDescription, String strLink, int currentPosition){
SubTrial obj = new SubTrial();
obj.setNamee(strUserName);
obj.setStartDate(strStartDate);
obj.setEndDate(strEndDate);
obj.setDescription(strDescription);
obj.setLink(strLink);
subscriptionAdapterList.editData(obj,currentPosition);
alertDialog.cancel();
}
}
Yes. Because once you exit the Application, the app memory is killed in the background process and opening up the app creates a new instance. Let's say for example, you created an editText and button which displays a Toast + text entered by the user to the user when clicked. The app memory will stop once you close and it will shutdown once you remove it from background memory. This method is called onDestroy().
So to prevent this, you can make use of android default local storages e.g
SQlite Database, Shared Preferences, Room Database
1. Sqlite database is android's offline local database which requires no internet access to store data. And data to be stored in SQlite Database should be in strings format like uri path. Storing bigger files or contents like images, audios, videos inside the SQLite database is not advisible to prevent exceptions such as;
FATAL EXCEPTION: main
11-06 15:16:17.199: E/AndroidRuntime(1789): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.demodbimage/com.example.demodbimage.ImagesList}: java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
2. Shared Preferences is good for storing very small data values in form of keys such as strings, boolean, integers. Take for instance, you want to prevent user from logging in after first time login is successful or you want to display dark theme next time once the user opt-in the first time.
3. Room Database is same as Sqlite database but Google recommends us to use it because it's easy to use, also provides databases syntax and very sensitive to errors.
Or you can make use of Online databases eg mySQL, MongoDB, Firebase Database, mariaDb etc.
Basically, RecyclerView is used in conjunction with the database like Room(Local DB) or API(Remote DB such as MySQL).
However, if you are creating a very lightweight project for your portfolio, I don't think it's a bad idea to use a datastore or sharedPrefereces. As with any program, List and Array commonly used in Kotlin are, of course, volatile.

Getting the button press on recycler view item which is created with method

I'm pretty new to Android Studio and Java overall so this might be simple question but I couldn't find any solutions or either couldn't use them to fix my issue.
So I have a RecyclerView which I can insert items from a list of pre-defined items with the function "addItems()" when I press to a button and display them.
Also those items have ImageButtons -which is just a transparent rectangle- to get individual clicks on them.
The purpose of these ImageButtons are to switch to a new activity which I defined in the "addItems()" method.
But the problem is, I can't catch -but they respond to the clicks- click on those items, and also I can't pass the activity class or the layout file.
To be exact, I want to use these buttons to switch to a new activity and display the info of that item there.
It's my first question here, so if I need to show any code, please tell me to.
NewsAdapter.java
package com.example.yiyecek2.Activities;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.yiyecek2.R;
import java.util.List;
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.NewsViewHolder>
{
Context mContext;
List<NewsItem> mData;
public NewsAdapter(Context mContext, List<NewsItem> mData) {
this.mContext = mContext;
this.mData = mData;
}
#NonNull
#Override
public NewsViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View layout;
layout = LayoutInflater.from(mContext).inflate(R.layout.lyt_restoran,viewGroup,false);
return new NewsViewHolder(layout);
}
// Changed below ----------
#Override
public void onBindViewHolder(#NonNull NewsViewHolder newsViewHolder, int position) {
// Bind data here
newsViewHolder.tvSellerName.setText(mData.get(position).getSellerName());
newsViewHolder.tvSellerAddress.setText(mData.get(position).getSellerAddress());
newsViewHolder.ivSellerImage.setImageResource(mData.get(position).getSellerImage());
newsViewHolder.tvMinCost.setText(mData.get(position).getMinCost());
newsViewHolder.tvMinTime.setText(mData.get(position).getMinTime());
newsViewHolder.tvDeliveryCost.setText(mData.get(position).getDeliveryCost());
newsViewHolder.tvClassToGo.setText(mData.get(position).getClassToGo());
// Line below is the buttons attached to the items which I aim to use on switching Activities
newsViewHolder.ibGoSellerPage.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
Intent intent = new Intent(SiparisActivity.this, classDominos.class);
startActivity(intent); // startActivity is marked red
}
});
}
// Changed above ----------
#Override
public int getItemCount() {
return mData.size();
}
public class NewsViewHolder extends RecyclerView.ViewHolder{
TextView tvSellerName, tvSellerAddress, tvMinCost, tvMinTime, tvDeliveryCost, tvClassToGo;
ImageView ivSellerImage;
ImageButton ibGoSellerPage;
public NewsViewHolder(#NonNull View itemView) {
super(itemView);
tvSellerName = itemView.findViewById(R.id.tvFoodName);
tvSellerAddress = itemView.findViewById(R.id.tvFoodDescription);
ivSellerImage = itemView.findViewById(R.id.ivFoodImage);
tvMinCost = itemView.findViewById(R.id.tvFoodCost);
tvMinTime = itemView.findViewById(R.id.tvMinTime);
tvDeliveryCost = itemView.findViewById(R.id.tvDeliveryCost);
tvClassToGo = itemView.findViewById(R.id.tvClassToGo);
ibGoSellerPage = itemView.findViewById(R.id.ibGoSellerPage);
//int position = getAdapterPosition();
//Toast.makeText(mContext.getApplicationContext(), "Position is: "+position, Toast.LENGTH_SHORT).show();
}
}
}
SiparisActivity.java //this is where I list restaurant items with ImageButtons said above.
package com.example.yiyecek2.Activities;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.example.yiyecek2.R;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import recyclerview.CustomItemAnimator;
public class SiparisActivity extends AppCompatActivity {
Button btnListRestaurants;
RecyclerView NewsRecyclerView;
NewsAdapter newsAdapter;
List<NewsItem> mData;
ImageButton ibGoSellerPage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_siparis);
// Hide the action bar
getSupportActionBar().hide();
NewsRecyclerView = findViewById(R.id.news_rv);
btnListRestaurants = (Button) findViewById(R.id.buttonListRestaurants);
NewsRecyclerView.setLayoutManager(new LinearLayoutManager(this));
NewsRecyclerView.setHasFixedSize(true);
NewsRecyclerView.setItemAnimator(new CustomItemAnimator());
// Get clicks on the "List Restaurants"
btnListRestaurants.setOnClickListener(new View.OnClickListener() {
int restaurantCount = 0;
#Override
public void onClick(View view) {
Toast toast = Toast.makeText(getApplicationContext(), "Listing Restaurants", Toast.LENGTH_SHORT);
toast.show();
Timer timerToTransition;
timerToTransition = new Timer();
TimerTask task = new TimerTask() {
public void run() {
addItems();
restaurantCount++;
if (restaurantCount > 9)
{
System.out.println(restaurantCount);
timerToTransition.cancel(); // Stops the timer when theres 10 Restaurants listed
}
}
};
timerToTransition.scheduleAtFixedRate(task,0,300); // waits 300ms before creating a new Restaurant
}
});
if (ibGoSellerPage != null) // Check if Restaurant button exists
{
System.out.println("ON CLICK HERE");
ibGoSellerPage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
System.out.println("ON CLICK HERE");
}
});
}
mData = new ArrayList<>();
// fill list news with pre defined data
// Adapter ini and setup
newsAdapter = new NewsAdapter(this,mData);
NewsRecyclerView.setAdapter(newsAdapter);
NewsRecyclerView.setLayoutManager(new LinearLayoutManager(this));
}
private void addItems()
{
RecyclerView.State state = null;
int switchInt = 0; // To use in the switch
// Random integer list to assign switchInt a random value
int[] intList;
intList = new int[]{0,1,2,3,4,5,6,7};
// Pick a random int
Random rand = new Random();
int rndInt = rand.nextInt(5);
// Check if the array's index isn't empty(-1)
while (intList[rndInt] != -1)
{
switchInt = (int) intList[rndInt];
intList[rndInt] = -1;
}
//System.out.println(rndInt);
switch(switchInt) {
case 0:
mData.add(0,new NewsItem("Domino's Pizza","Sarıgöl, Ordu Cd. No:128, 34240 Gaziosmanpaşa/İstanbul",
R.drawable.dominos,"32 TL","30 dk.","0 TL","classDominos")); // I'm trying to catch that "classDominos" to use to switch Activity
break;
case 1:
mData.add(0,new NewsItem("Migros","Bağlarbaşı, Küçükköy Yolu Cd., 34245 Gaziosmanpaşa/İstanbul",
R.drawable.migroslogo,"32 TL","25 dk.","0 TL", "classDominos"));
break;
case 2:
mData.add(0,new NewsItem("KFC","Yeşilpınar Mah. Şehit Metinkaya Sok Vialand AVM No:11 Mağaza No:237, 34065 Eyüpsultan",
R.drawable.kfclogo,"32 TL","35 dk.","3 TL", "classDominos"));
break;
case 3:
mData.add(0,new NewsItem("Popeyes","Yeşilpınar Mah. Şehit Metin Kaya Sok. No:11 K:3 Vialand AVM, 34065",
R.drawable.popeyeslogo,"32 TL","35 dk.","3 TL", "classDominos"));
break;
case 4:
mData.add(0,new NewsItem("Mado","İslambey, Hz. Halid Blv. No:43 D:B, 34050 Eyüpsultan/İstanbul",
R.drawable.madologo,"32 TL","35 dk.","3 TL", "classDominos"));
break;
default:
break;
}
System.out.println("Added item");
newsAdapter.notifyItemInserted(0);
NewsRecyclerView.getLayoutManager().smoothScrollToPosition(NewsRecyclerView, state, 0);
// Un-commenting the lines below crash the app when "Listing Restaurants" (Creating items)
//ibGoSellerPage = (ImageButton) findViewById(R.id.ibGoSellerPage);
/*ibGoSellerPage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
System.out.println("ON CLICK HERE");
}
});
*/
}
}
I can see the individual buttons in the profiler but how to catch clicks on them? (You can see I'm holding the button on the right)
Profiler Screenshot
I think the problem with you is that the click event happen on the screen in another view
By making a transparent rectangle i think the click go to the parent view
Try to test that for ex:
<LinearLayout
android:id="#+id/layout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
handle the click on layout view if it work so you need to change the transparent rectangle button to a bold one or another approach
better to add some code from your side to help us understand the problem well

Update layout after writing SharedPreferences?

My first thread here - sorry if the text formatting is bad.
I use Android Studio 3.1.3 API27 and work on an app for Smartphone.
The app currently consists of 1 activity (split in 3 fragments), a second activity and 5 xml files.
By using a ViewPager, I'm able to swipe through the 3 fragments.
The 2nd fragment (middle fragment) contains 2 buttons that each open the 2nd activity, which contains many color buttons.
When clicking on the color buttons, I can change the background colors of the 1st fragment.
After choosing a color, the 2nd activity gets closed and I'm back in activity 1 -> fragment2.
It works, but the PROBLEM is that I always have to swipe to the 3rd fragment,
then back to the 2nd and then to the 1st.
If I don't do this, the colors of fragment 1 will remain the old ones.
Now I'm looking for a way to update the layout of fragment 1 as soon as I press a color button of activity 2.
I already tried this:
when writing the SharedPreferences (Activity2), I use editor.apply() instead of editor.commit()
when reading the SharedPreferences (Activity1 -> Fragment1), I use Context.MODE_MULTI_PROCESS instead of Context.MODE_PRIVATE
using viewpage.setOffscreenPageLimit(0); in the MainActivity inside of my public void SetUpViewPager(ViewPager viewpage) method.
Nothing helped, though.
This is how it looks like:
MainActivity.java (Activity 1):
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity
{
ViewPager vp;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager vp = findViewById(R.id.vp);
SetUpViewPager(vp);
}
public void SetUpViewPager(ViewPager viewpage)
{
MyViewPagerAdapter Adapter = new MyViewPagerAdapter(getSupportFragmentManager());
Adapter.AddPageFragment(new Page_1(), "Page 1");
Adapter.AddPageFragment(new Page_2(), "Page 2");
Adapter.AddPageFragment(new Page_3(), "Page 3");
viewpage.setOffscreenPageLimit(0);
viewpage.setAdapter(Adapter);
}
public class MyViewPagerAdapter extends FragmentPagerAdapter
{
private List<Fragment> MyFragment = new ArrayList<>();
private List<String> MyPageTitle = new ArrayList<>();
public MyViewPagerAdapter(FragmentManager manager)
{
super(manager);
}
public void AddPageFragment(Fragment Frag, String Title)
{
MyFragment.add(Frag);
MyPageTitle.add(Title);
}
#Override
public Fragment getItem(int i)
{
return MyFragment.get(i);
}
#Nullable
#Override
public CharSequence getPageTitle(int position)
{
return MyPageTitle.get(position);
}
#Override
public int getCount()
{
return 3;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
int id = item.getItemId();
if (id == R.id.action_settings)
{
return true;
}
return super.onOptionsItemSelected(item);
}
}
Page_1.java (Activity 1 -> Fragment 1):
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.constraint.ConstraintLayout;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
import static android.content.Context.MODE_PRIVATE;
public class Page_1 extends Fragment
{
int backgroundColorLeft, backgroundColorRight, textColorLeft, textColorRight; // Variables for SharedPreferences
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View PageOne = inflater.inflate(R.layout.page1, container, false); // Link view to layout?
return PageOne;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState)
{
SharedPreferences prefs = getActivity().getSharedPreferences("bgColor", Context.MODE_MULTI_PROCESS); // Load saved shared file
backgroundColorLeft = prefs.getInt("backgroundColorLeft", backgroundColorLeft); // Load saved background color for left layout
textColorLeft = prefs.getInt("textColorLeft", textColorLeft); // Load saved text color for left layout
backgroundColorRight = prefs.getInt("backgroundColorRight", backgroundColorRight); // Load saved background color for right layout
textColorRight = prefs.getInt("textColorRight", textColorRight); // Load saved text color for right layout
RelativeLayout relLayoutLeft = getActivity().findViewById(R.id.rel_layout_left); // Link variable to ID of left layout
relLayoutLeft.setBackgroundColor(backgroundColorLeft); // Change background color of left layout
TextView tvLeft = getActivity().findViewById(R.id.tv_left); // Link variable to ID
tvLeft.setTextColor(textColorLeft); // Change text color of left layout
RelativeLayout relLayoutRight = getActivity().findViewById(R.id.rel_layout_right); // Link variable to ID of right layout
relLayoutRight.setBackgroundColor(backgroundColorRight); // Change background color of right layout
TextView tvRight = getActivity().findViewById(R.id.tv_right); // Link variable to ID
tvRight.setTextColor(textColorRight); // Change text color of right layout
super.onActivityCreated(savedInstanceState);
}
}
Page_2.java (Activity 1 -> Fragment 2):
package com.example.konstantin.clipcodes_swiping;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.RelativeLayout;
import static android.content.Context.MODE_PRIVATE;
public class Page_2 extends Fragment
{
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View PageTwo = inflater.inflate(R.layout.page2, container, false);
Button buttonLeft = PageTwo.findViewById(R.id.button_left); // Link variable to ID of left button
buttonLeft.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
int pos = 1; // Set position to left
setPosition(pos); // Load setColor method and send 2 color values
}
});
Button buttonRight = PageTwo.findViewById(R.id.button_right); // Link variable to ID of right button
buttonRight.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
int pos = 2; // Set position to right
setPosition(pos); // Load setColor method and send 2 color values
}
});
return PageTwo;
}
public void setPosition (int pos) // Start second activity to choose colors
{
Intent intentPos = new Intent(getActivity(), Page_4_Colors.class); // Create intent for current Activity and target activity
SharedPreferences prefs = getActivity().getSharedPreferences("bgColor", Context.MODE_MULTI_PROCESS); // Create new SharedPreferences instance
SharedPreferences.Editor editor = prefs.edit(); // Assign variable to editor function
editor.putInt("position", pos); // Write selected position (int) inside of editor
editor.apply(); // Save values, close process
getActivity().startActivity(intentPos); // Start second activity
}
}
Page_3.java (Activity 1 -> Fragment 3):
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class Page_3 extends Fragment
{
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View PageThree = inflater.inflate(R.layout.page3, container, false);
return PageThree;
}
}
Page_4_Colors.java (Activity 2):
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class Page_4_Colors extends Activity
{
int pos;
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.page4_colors);
SharedPreferences prefs = getSharedPreferences("bgColor", MODE_MULTI_PROCESS); // Load saved shared file
pos = prefs.getInt("position", pos); // Load saved position (int)
Log.wtf("Position", String.valueOf(pos)); // Show pos value in Log
Button buttonWhite = findViewById(R.id.button_white);
buttonWhite.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
setColor(getResources().getColor(R.color.white), getResources().getColor(R.color.black)); // Load setColor method and send 2 color values
}
});
Button buttonYellow = findViewById(R.id.button_yellow);
buttonYellow.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
setColor(getResources().getColor(R.color.yellow), getResources().getColor(R.color.black)); // Load setColor method and send 2 color values
}
});
Button buttonOrange = findViewById(R.id.button_orange);
buttonOrange.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
setColor(getResources().getColor(R.color.orange), getResources().getColor(R.color.black)); // Load setColor method and send 2 color values
}
});
Button buttonRed = findViewById(R.id.button_red);
buttonRed.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
setColor(getResources().getColor(R.color.red), getResources().getColor(R.color.black)); // Load setColor method and send 2 color values
}
});
Button buttonGreen = findViewById(R.id.button_green);
buttonGreen.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
setColor(getResources().getColor(R.color.green), getResources().getColor(R.color.black)); // Load setColor method and send 2 color values
}
});
Button buttonBlue = findViewById(R.id.button_blue);
buttonBlue.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
setColor(getResources().getColor(R.color.blue), getResources().getColor(R.color.white)); // Load setColor method and send 2 color values
}
});
}
public void setColor (int backgroundColor, int textColor) // Write color values into SharedPreferences
{
SharedPreferences prefs = getSharedPreferences("bgColor", MODE_MULTI_PROCESS); // Create new SharedPreferences instance
SharedPreferences.Editor editor = prefs.edit(); // Assign variable to editor function
if (pos == 1)
{
editor.putInt("backgroundColorLeft", backgroundColor); // Write background color (int) inside of editor
editor.putInt("textColorLeft", textColor); // Write text color (int) inside of editor
}
if (pos == 2)
{
editor.putInt("backgroundColorRight", backgroundColor); // Write background color (int) inside of editor
editor.putInt("textColorRight", textColor); // Write text color (int) inside of editor
}
editor.apply(); // Save values, close process
this.finish(); // Close this activity
}
}
Thanks for any help!
use EventBus
unregister and register EventBus in Page_1 onStop() and onStart()
EventBus.getDefault().unregister(this)
EventBus.getDefault().register(this)
and use this for post the value
EventBus.getDefault().post(new MessageEvent("Change Color"));
and this function will handle the MessageEvent
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
//change the color here
//add this function in Page_1
}
when you update the value of color. put in MessageEvent documentation
You can update the UI (or at least the color related part) for each fragment in the onResume() method, thus, when you return from the second activity, it will refresh.
When a Fragment is made visible (i.e., the selected page in your ViewPager), its setUserVisibleHint() method is called. You can override that method in your Fragment and use it to trigger a refresh.
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser){
//you can check if the color is changed then refresh the fragment if not then don't do anything
//here you should refresh your fragment , this will called every time you
//view this fragment in all cases even if you didn't move to the
//third tab
}
}
How To Refresh A Fragment
Fragment currentFragment = getFragmentManager().findFragmentByTag("YourFragmentTag");
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.detach(currentFragment);
fragmentTransaction.attach(currentFragment);
fragmentTransaction.commit();

Displaying CardViews inside a RecyclerView using FirebaseUI and Firebase database

I am trying to display CardViews inside a RecyclerView, each card will represent a cheese object.
This cheese object has 6 instance variables.
This is my Cheese.java :
public class Cheese {
private String CheeseName;
private String CheeseCountryOfOrigin;
private String CheeseDayMade;
private String CheeseDayExpire;
private String CheeseDescription ;
private String CheesePrice;
public Cheese(){} //Required for firebase
public Cheese(String CheeseName, String CheeseCountryOfOrigin, String CheeseDayMade, String CheeseDayExpire, String CheeseDescription, String CheesePrice) {
this.CheeseName = CheeseName;
this.CheeseCountryOfOrigin = CheeseCountryOfOrigin;
this.CheeseDayMade = CheeseDayMade;
this.CheeseDayExpire = CheeseDayExpire;
this.CheeseDescription = CheeseDescription;
this.CheesePrice = CheesePrice;
}
public String getCheeseName() {
return CheeseName;
}
public String getCheeseCountryOfOrigin() {
return CheeseCountryOfOrigin;
}
public String getCheeseDayMade() {
return CheeseDayMade;
}
public String getCheeseDayExpire() {
return CheeseDayExpire;
}
public String getCheeseDescription() {
return CheeseDescription;
}
public String getCheesePrice() {
return CheesePrice;
}
}
and this is my cheese_card.xml (I hardcoded some android:text for better understanding): cheese_card.xml
my RecyclerView is in a fragment.
This is my fragment:
fragment_cheeses_list.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/cheeses_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical">
</android.support.v7.widget.RecyclerView>
all my cheese items are already in my Firebase Real-Time Database. To make my life simpler I am trying to use FirebaseUI to populate my RecyclerView with data from my Firebase database.
This is my CheesesListFragment.java, which is displayed in my MainActivity:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.CardView;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
public class CheeseListFragment extends Fragment {
private static final String TAG = "CheesesListFragment";
private FirebaseDatabase aFirebaseDatabase;
private DatabaseReference aCheesesDatabaseReference;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.e(TAG, "onCreateView Started Successfully");
//Create the recycler view object
RecyclerView cheesesRecycler = (RecyclerView) inflater.inflate(R.layout.fragment_cheeses_list, container, false);
//Add a grid layout manager to the recycler view
GridLayoutManager layoutManager = new GridLayoutManager(getActivity(), 1);
cheesesRecycler.setLayoutManager(layoutManager);
cheesesRecycler.setHasFixedSize(true);
aFirebaseDatabase = FirebaseDatabase.getInstance();
aCheesesDatabaseReference = aFirebaseDatabase.getReference().child("cheeses");
//Query the cheeses in firebase db using firebaseUI instead of addChildEventListener
Query query = aCheesesDatabaseReference;
//configuration for the FirebaseRecyclerAdapter
FirebaseRecyclerOptions<Cheese> options =
new FirebaseRecyclerOptions.Builder<Cheese>()
.setQuery(query, Cheese.class)
.build();
FirebaseRecyclerAdapter adapter = new FirebaseRecyclerAdapter<Cheese, CheeseViewHolder>(options) {
#Override
public CheeseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Create a new instance of the ViewHolder, in this case we are using a custom
// layout called R.layout.cheese_card for each item
CardView cv = (CardView) LayoutInflater.from(parent.getContext())
.inflate(R.layout.cheese_card, parent, false);
return new CheeseViewHolder(cv);
}
#Override
protected void onBindViewHolder(CheeseViewHolder holder, int position, Cheese model) {
CheeseViewHolder myHolder = (CheeseViewHolder)holder;
myHolder.cheeseName.setText(model.getCheeseName());
myHolder.cheeseCountryOfOrigin.setText(model.getCheeseCountryOfOrigin());
myHolder.cheeseDayMade.setText(model.getCheeseDayMade());
myHolder.cheeseDayExpire.setText(model.getCheeseDayExpire());
myHolder.cheeseDescription.setText(model.getCheeseDescription());
myHolder.cheesePrice.setText(model.getCheesePrice());
}
};
//Set the adapter to the recycle View
cheesesRecycler.setAdapter(adapter);
return cheesesRecycler;
}
public static class CheeseViewHolder extends RecyclerView.ViewHolder {
CardView cardView;
TextView CheeseName;
TextView CheeseCountryOfOrigin;
TextView CheeseDayMade;
TextView CheeseDayExpire;
TextView CheeseDescription;
TextView CheesePrice;
public CheeseViewHolder (CardView v){
super(v);
cardView = v;
CheeseName = (TextView)cardView.findViewById(R.id.cheese_name);
CheeseCountryOfOrigin= (TextView)cardView.findViewById(R.id.cheese_origin);
CheeseDayMade= (TextView)cardView.findViewById(R.id.cheese_day_made);
CheeseDayExpire= (TextView)cardView.findViewById(R.id.cheese_day_expire);
CheeseDescription= (TextView)cardView.findViewById(R.id.cheese_description);
CheesePrice= (TextView)cardView.findViewById(R.id.cheese_price);
}
}
}
So my questions are: (answering any of them is welcomed and very helpful)
If i get it right, onCreateViewHolder is supposed to make ViewHolders for my Cheese object using my cheese_card.xml . if so, assuming I delete onBindingViewHolder am I suppose to see lots of view holders that look like my cheese_card.xml?
in onBindingViewHolder in setText : how can I get my TextViews to get a value from my firebase?
I am new to programming and not sure about onCreateViewHolder, onBindingHolder and cheesesViewHolder.I am not sure what every code I writed there means as some of them are copy-pasted.If I got it all wrong, can you please explain how can I reach my desired outcome, and what I did wrong?
Thank you, in advance :)
Modify onBindingViewHolder and cheesesViewHolder. Because in onBindingViewHolder you will bind data with Views not Views with they ids. Bind Views with they ids inside cheesesViewHolder. For example:
CardView cardView;
TextView cheese_name;
TextView cheese_origin;
public CheeseViewHolder(CardView v) {
super(v);
cardView = v;
cheese_name = (TextView) cardView.findViewById(R.id.cheese_name);
cheese_origin = (TextView) cardView.findViewById(R.id.cheese_origin);
// and so on...
}
Then inside onBindingViewHolder you will do something like this:
#Override
protected void onBindViewHolder(CheeseViewHolder holder, int position, Cheese model) {
cheesesViewHolder myHolder = (cheesesViewHolder)holder;
myHolder.cheese_name.setText(model.getCheeseName());
myHolder. cheese_origin.setText(model.getCheeseOrigin());
//and so on...
}
I was able to eventually fix my problem and get onCreateViewHolder and onBindViewHolder to start simply by adding
adapter.startListening();
to my onStart method. like this:
#Override
public void onStart() {
super.onStart();
Log.e(TAG,"onStart Started Successfully");
adapter.startListening();
}
And I edited the code using #Yupi suggestion.

Image for ImageButton doesn't change as intended

My goal here is to change an Image from an ImageButton(ibChamp).
package com.example.custombuilds;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;z
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
public class Champions extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.champions);
ImageButton ibAnnie = (ImageButton) findViewById(R.id.ibAnnie);
ibAnnie.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Check this for errors
RelativeLayout test = (RelativeLayout) findViewById(R.id.layoutChampions);
LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(R.layout.create_build_page, null);
test.addView(view);
ImageButton img = (ImageButton) view.findViewById(R.id.ibChamp);
img.setImageResource(R.drawable.ic_launcher);
try {
Intent open = new Intent("android.intent.action.CREATE");
startActivity(open);
} catch (Exception e) {
}
}
});
}
}
Note that the ImageButton ibChamp is from the xml layout create_build_page, and not the xml champions.
This code runs without crashing, but the Image from the Imagebutton ibChamp does not change, which is what I am trying to do. I will be happy to provide any other additional information.
You are inflating "ibChamp" in onClick. That creates a new ImageButton. You will not see it until you use "addView" from the parent.
You can add your XML, but you need to get a reference to an existing button in Activity in order to change it. Or else add the new button and remove an old one...
In other words, change this:
LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(R.layout.create_build_page, null);
ImageButton img = (ImageButton) view.findViewById(R.id.ibChamp);
to this:
ImageButton img = (ImageButton)findViewById(R.id.ibChamp);
And it will probably do what you want.
you need to call addView() for this inflated view
View view = layoutInflater.inflate(R.layout.create_build_page, null);

Categories