Add two negative numbers using TextWatcher - android-studio

I'm absolute beginner. I will to add two negativ numbers and the result display with TextWatcher.
When I try to edit the second (negative) number, the app is crashes. I don't know where is the problem.
Main Activity java code is
...
package com.example.addnegativnumbers;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
EditText Number1, Number2;
TextView Result;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Number1 = findViewById(R.id.Number1);
Number2 = findViewById(R.id.Number2);
Result = findViewById(R.id.Result);
TextWatcher textWatcher = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (!Number1.getText().toString().equals("") && !Number2.getText().toString().equals("")) {
int temp1 = Integer.parseInt(Number1.getText().toString());
int temp2 = Integer.parseInt(Number2.getText().toString());
Result.setText(String.valueOf(temp1 + temp2));
}
;
}
#Override
public void afterTextChanged(Editable editable) {
}
};
Number1.addTextChangedListener(textWatcher);
Number2.addTextChangedListener(textWatcher);
}
}
...

Part of activity_main.xml:
<EditText
android:id="#+id/Number1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:layout_marginTop="40dp"
android:ems="10"
android:hint="Enter number 1"
android:inputType="numberSigned|textPersonName"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="#+id/Number2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:ems="10"
android:hint="Enter number 2"
android:inputType="numberSigned|textPersonName"
app:layout_constraintStart_toStartOf="#+id/Number1"
app:layout_constraintTop_toBottomOf="#+id/Number1" />
Part of Logcat
2022-03-17 06:55:26.959 21618-21618/com.example.addnegativnumbers E/InputEventSender: Exception dispatching finished signal.
2022-03-17 06:55:26.960 21618-21618/com.example.addnegativnumbers E/MessageQueue-JNI: Exception in MessageQueue callback: handleReceiveCallback
2022-03-17 06:55:26.968 21618-21618/com.example.addnegativnumbers E/MessageQueue-JNI: java.lang.NumberFormatException: For input string: "-"
at java.lang.Integer.parseInt(Integer.java:513)
at java.lang.Integer.parseInt(Integer.java:556)
at com.example.addnegativnumbers.MainActivity$1.onTextChanged(MainActivity.java:39)
Line 39 is:
int temp2 = Integer.parseInt(Number2.getText().toString());
The problem is the string "-"

Related

Custom ListView with CustomAdapter Not Showing Up

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

How to implement CountDownTimer in Recyclerview?

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.

How do I Remove Cell Padding in a Gridview

I'm hoping someone can help me. I have created a Sudoku app. I have a grid view that shows string text from a list view. I have a problem with my layout of the Grid View on my phone and tablet; , see 1st and 2nd screens below .
What I'm trying to do is set the screen, so the grid display neatly just above the numbers 1 to 5. Ideally I'd like it to render appropriately on tablet and phone.
On a Phone the last row of the sudoku grid showing underneath the first set of button button See firstImage. Whereas on a Tablet there is a huge gap between the gridvview and the Buttons
What I have I tried so far:
I tried android:layout_above btn1. But that chopped off the last row of the sudoku grid and I had to drag the grid up and down to see the last row on a phone. It also caused the app to crash of a phone. Not good.
I tried putting a frame layout inside the relative layout and putting the gridview inside of that. But that had the also chopped off the last row of the sudoku grid as per layout_above.
Really what I'd like to do is, on a phone I would like to remove or reduce the padding above and below each number in each cell in the grid view. As the cell padding makes each cell in the grid 2 - 3 times bigger than it needs to be. This is a problem on a 5" mobile phone screen. I have tried the following and none of them worked.
How do I get rid of unwanted padding in a Listview row
android:gravity - Made no Difference
How to avoid space between imageview and gridview in linearlayout
listSelector=”#null” - Made no difference
Removing the extra padding in a GridView in android
stretchMode(0); - Everything disappeared.
How do I get rid of unwanted padding in a Listview row
view.setMinimumHeight(0); - Made no difference.
I also tried view.setPadding(); it was useful in that the padding on the left hand side was removed, but it didn't remove the papdding at the top or bottom.
view.setPadding(dpToPx(0, parent), 0, 0, 0);
I am at a loss at this stage about how to move this forward and am worried that trying all these different things is making me more confused. If someone could point me in the correct direction I'd be very grateful. Code is shown below.
content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.example.admin1.sudoku.MainActivity"
android:background="#663399"
tools:showIn="#layout/activity_main">
<Button
android:id="#+id/btn1"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/btn1Label"
android:layout_above="#+id/btn6"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignBottom="#+id/btn2"
/>
<Button
android:id="#+id/btn2"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/btn2Label"
android:layout_above="#+id/btn7"
android:layout_toLeftOf="#+id/btn8"
android:layout_toStartOf="#+id/btn8" />
<Button
android:id="#+id/btn3"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/btn3Label"
android:layout_alignTop="#+id/btn2"
android:layout_toRightOf="#+id/btn2"
android:layout_toEndOf="#+id/btn2" />
<Button
android:id="#+id/btn4"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/btn4Label"
android:layout_alignTop="#+id/btn3"
android:layout_toRightOf="#+id/btn3"
android:layout_toEndOf="#+id/btn3" />
<Button
android:id="#+id/btn5"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/btn5Label"
android:layout_alignTop="#+id/btn4"
android:layout_toRightOf="#+id/btn4"
android:layout_toEndOf="#+id/btn4" />
<Button
android:id="#+id/btn6"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/btn6Label"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<Button
android:id="#+id/btn7"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/btn7Label"
android:layout_alignParentBottom="true"
android:layout_toRightOf="#+id/btn6"
android:layout_toEndOf="#+id/btn6" />
<Button
android:id="#+id/btn8"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/btn8Label"
android:layout_alignParentBottom="true"
android:layout_toRightOf="#+id/btn7"
android:layout_toEndOf="#+id/btn7" />
<Button
android:id="#+id/btn9"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/btn9Label"
android:layout_alignParentBottom="true"
android:layout_toRightOf="#+id/btn3"
android:layout_toEndOf="#+id/btn3" />
<Button
android:id="#+id/btn0"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/btn0Label"
android:layout_alignParentBottom="true"
android:layout_toRightOf="#+id/btn9"
android:layout_toEndOf="#+id/btn9" />
<Button
android:id="#+id/btnCheck"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/btnCheckLabel"
android:layout_below="#+id/gridView1"
android:layout_alignTop="#+id/btn5"
android:layout_toRightOf="#+id/btn5"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
<Button
android:id="#+id/btnHint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/btnHintLabel"
android:layout_alignTop="#+id/btn0"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignLeft="#+id/btnCheck"
android:layout_alignStart="#+id/btnCheck" />
<GridView
android:id="#+id/gridView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numColumns="9"
android:columnWidth="0dp"
android:horizontalSpacing="5dp"
android:verticalSpacing="5dp"
android:clipChildren="true"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:background="#C0C0C0"
android:padding="5dp"
android:textSize="12sp"
android:stretchMode="columnWidth"
android:gravity="clip_vertical"
/>
</RelativeLayout>
MainActivity.java
package com.example.admin1.sudoku;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.DisplayMetrics;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.GridView;
import android.widget.ArrayAdapter;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.graphics.Color;
import android.widget.Toast;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import android.content.res.Resources;
import android.media.MediaPlayer;
public class MainActivity extends AppCompatActivity {
// Class that holds the creation of a Sudoku Puzzle
private SudokuPuzzle clsSudoku;
//Variables used throughout the program.
private final int iMaxCells = 81;
private String[] stResult; // Holds the solution to the current puzzle
private int[] iExcluded; // Holds all the blue cells (clues given to the user at the start)
// Placed into List for fast searching
private int iElement;
private boolean blShowResult; // Indicates if the user has clicked Show Result
private boolean blGiveHint; // Indicates if the user has clicked Give Hint
private boolean blSoundOn;
// UI Elements
private View tvCell;
private GridView gridView;
private Menu menu;
private MediaPlayer mp = null;
/* Lists
lstitems holds all the items in the current board including user entries
lstExclude holds all the blue cells (clues given to the user at the start)
adapter
*/
private List<String> lstItems;
private ArrayAdapter<String> adapter ;
private List<Integer> lstExcluded;
public MainActivity() {
stResult = new String[iMaxCells];
blGiveHint = false;
blShowResult = false;
iElement = 0;
blSoundOn = false;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Declare used buttons
Button btn1 = (Button) findViewById(R.id.btn1);
Button btn2 = (Button) findViewById(R.id.btn2);
Button btn3 = (Button) findViewById(R.id.btn3);
Button btn4 = (Button) findViewById(R.id.btn4);
Button btn5 = (Button) findViewById(R.id.btn5);
Button btn6 = (Button) findViewById(R.id.btn6);
Button btn7 = (Button) findViewById(R.id.btn7);
Button btn8 = (Button) findViewById(R.id.btn8);
Button btn9 = (Button) findViewById(R.id.btn9);
Button btn0 = (Button) findViewById(R.id.btn0);
Button btnHint = (Button) findViewById(R.id.btnHint);
Button btnCheck = (Button) findViewById(R.id.btnCheck);
//Creates a new Game
clsSudoku = new SudokuPuzzle();
newGame();
gridView = (GridView) findViewById(R.id.gridView1);
gridView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
if (blGiveHint == true){
blGiveHint = false;
//Initialise any hinted cells back to white
clearCells();
}
if (!blShowResult){
tvCell = gridView.getChildAt(iElement);
try{
tvCell.setBackgroundColor(Color.WHITE);
iElement = position;
tvCell = gridView.getChildAt(iElement);
tvCell.setBackgroundColor(Color.RED);
}
catch(Exception e){
}
}
}
});
gridView.setAdapter(adapter = new ArrayAdapter<String>(MainActivity.this,
android.R.layout.simple_list_item_1, lstItems) {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
view.setPadding(dpToPx(0, parent), 0, 0, 0);
view.setMinimumHeight(0);
if (position == iElement && !blShowResult){
view.setBackgroundColor(Color.RED);
}
else if (lstExcluded.contains(position)) {
view.setBackgroundColor(Color.WHITE);
}
else{
view.setBackgroundColor(Color.CYAN);
}
return view;
}
#Override
public boolean isEnabled(int position) {
// Item position which you want to disable.
if (!lstExcluded.contains(position) ) {
return false;
}
else {
return true;
}
}
});
btn1.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if (adapter.isEnabled(iElement) && !blShowResult){
lstItems.set(iElement, "1");
adapter.notifyDataSetChanged();
}
}
});
btn2.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if (adapter.isEnabled(iElement) && !blShowResult){
lstItems.set(iElement, "2");
adapter.notifyDataSetChanged();
}
}
});
btn3.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if (adapter.isEnabled(iElement) && !blShowResult){
lstItems.set(iElement, "3");
adapter.notifyDataSetChanged();
}
}
});
btn4.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if (adapter.isEnabled(iElement) && !blShowResult){
lstItems.set(iElement, "4");
adapter.notifyDataSetChanged();
}
}
});
btn5.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if (adapter.isEnabled(iElement) && !blShowResult){
lstItems.set(iElement, "5");
adapter.notifyDataSetChanged();
}
}
});
btn6.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if (adapter.isEnabled(iElement) && !blShowResult){
lstItems.set(iElement, "6");
adapter.notifyDataSetChanged();
}
}
});
btn7.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if (adapter.isEnabled(iElement) && !blShowResult){
lstItems.set(iElement, "7");
adapter.notifyDataSetChanged();
}
}
});
btn8.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if (adapter.isEnabled(iElement) && !blShowResult){
lstItems.set(iElement, "8");
adapter.notifyDataSetChanged();
}
}
});
btn9.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if (adapter.isEnabled(iElement) && !blShowResult){
lstItems.set(iElement, "9");
adapter.notifyDataSetChanged();
}
}
});
btn0.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if (adapter.isEnabled(iElement) && !blShowResult){
lstItems.set(iElement, "");
adapter.notifyDataSetChanged();
}
}
});
btnHint.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
blGiveHint = true;
giveHint();
}
});
btnCheck.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
checkCorrect();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
this.menu = menu;
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
switch(id){
case R.id.new_game:
createNewGame();
return true;
case R.id.show_result:
getResult();
return true;
case R.id.sound_toggle:
setSoundSettings();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
// Populate a list for fast searching later
private void populateExcludeList(int[] ipiArray){
lstExcluded.clear();
for (int iCnt = 0; iCnt < ipiArray.length; iCnt++){
lstExcluded.add(ipiArray[iCnt] - 1);
}
Collections.sort(lstExcluded);
}
// Populate a list for fast searching later
private void setBoard(String[] ipstArray){
lstItems.clear();
for (int iCnt = 0; iCnt < ipstArray.length; iCnt++){
lstItems.add(ipstArray[iCnt]);
}
}
// Create a new puzzle
private void newGame(){
String[] stNumbers = new String[iMaxCells];
blShowResult = false;
clsSudoku.swapTwoNumbers();
clsSudoku.swapTwoColumns();
clsSudoku.swapTwoBlocks();
clsSudoku.rotateNintyDegrees();
clsSudoku.clearNumbers();
stNumbers = clsSudoku.getResult("User");
stResult = clsSudoku.getResult("Result");
iExcluded = clsSudoku.getRemoved();
if (lstItems == null) {
lstItems = new ArrayList<String>(Arrays.asList(stNumbers));
}
else {
setBoard(stNumbers);
}
lstExcluded = new ArrayList<Integer>();
populateExcludeList(iExcluded);
iElement = lstExcluded.get(0);
}
private void createNewGame(){
if ( !lstItems.isEmpty() ){
lstItems.clear();
}
newGame();
adapter.notifyDataSetChanged();
}
private void getResult(){
blShowResult = true;
setBoard(stResult);
lstExcluded = new ArrayList<Integer>();
populateExcludeList(iExcluded);
adapter.notifyDataSetChanged();
}
public void giveHint(){
for (int iCnt = 0; iCnt < iMaxCells; iCnt++){
tvCell = gridView.getChildAt(iCnt);
try{
if (lstItems.get(iCnt).equalsIgnoreCase(stResult[iCnt]) == false && blGiveHint == true){
tvCell.setBackgroundColor(Color.RED);
}
else if(lstItems.get(iCnt).equalsIgnoreCase(stResult[iCnt]) && lstExcluded.contains(iCnt) ){
tvCell.setBackgroundColor(Color.WHITE);
}
}
catch(Exception e){
Toast.makeText(this, "Error: " + e.getMessage(),Toast.LENGTH_LONG).show();
}
}
}
public void checkCorrect(){
boolean blErrorFound = false;
int iCntErrors = 0;
int iCntBlanks = 0;
String stMessage = "";
for (int iCnt = 0; iCnt < iMaxCells; iCnt++){
if ( (lstItems.get(iCnt).equalsIgnoreCase("") == true)
){
iCntBlanks = iCntBlanks + 1;
blErrorFound = true;
}
else if((lstItems.get(iCnt).equalsIgnoreCase(stResult[iCnt]) == false) &&
(lstItems.get(iCnt).equalsIgnoreCase("") == false)
){
iCntErrors = iCntErrors + 1;
blErrorFound = true;
}
}
if (!blErrorFound){
stMessage = "Congratulations !!! Your solution is correct";
if (blSoundOn == true){
playSound("congratulations");
}
}
else{
stMessage = "You have " + iCntErrors + " errors and " + iCntBlanks + " squares left to do";
if (blSoundOn == true){
playSound("wrong");
}
}
Toast.makeText(getApplicationContext(), stMessage, Toast.LENGTH_LONG).show();
}
private void clearCells(){
for (int iCnt = 0; iCnt < iMaxCells; iCnt++){
tvCell = gridView.getChildAt(iCnt);
if(lstExcluded.contains(iCnt) ){
tvCell.setBackgroundColor(Color.WHITE);
}
}
}
private void setSoundSettings() {
MenuItem miMenu = menu.findItem(R.id.sound_toggle);
if (blSoundOn) {
blSoundOn = false;
miMenu.setTitle("Turn Sound On");
} else {
blSoundOn = true ;
miMenu.setTitle("Turn Sound Off");
}
}
public void playSound(String stFileName){
int iSoundId;
if (mp != null){
mp.reset();
mp.release();
}
Resources res = getApplicationContext().getResources();
iSoundId = res.getIdentifier(stFileName, "raw", getApplicationContext().getPackageName());
mp = MediaPlayer.create(getApplicationContext(), iSoundId);
mp.start();
}
public int dpToPx(int dp, View v) {
DisplayMetrics displayMetrics = v.getContext().getResources().getDisplayMetrics();
return Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
}
}

selected Image button changes its position in recyclerView when scrolling

i have a recyclerview in my MainActivity and i'm showing no of items in list manner through RecyclerView.Adapter. here is my recyclerview_list_items.xml file,
<?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:orientation="vertical"
android:padding="10dp">
<ImageView
android:id="#+id/person_photo"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:scaleType="centerCrop"
android:src="#drawable/rounded_img" />
<TextView
android:id="#+id/person_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/btnfollow"
android:layout_toRightOf="#+id/person_photo"
android:ellipsize="end"
android:paddingLeft="10dp"
android:paddingRight="4dp"
android:singleLine="true"
android:text="*********"
android:textColor="#303030"
android:textSize="17sp" />
<ImageButton
android:id="#+id/btnfollow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="8dp"
android:layout_marginTop="4dp"
android:background="#drawable/follow_inactive" />
</RelativeLayout>
and here is my adapter class file,
public class SuggestionListItemAdapter extends RecyclerView.Adapter<SuggestionListItemAdapter.MyViewHolder> {
private List<MovieData> moviesList;
Context context;
private boolean isButtonClicked = false;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView person_name;
ImageView person_photo;
ImageButton person_follow;
public MyViewHolder(View view) {
super(view);
person_photo = (ImageView) view.findViewById(R.id.person_photo);
person_name = (TextView) view.findViewById(R.id.person_name);
person_follow = (ImageButton) view.findViewById(R.id.btnfollow);
}
}
public SuggestionListItemAdapter(Context mContext,List<MovieData> moviesList) {
this.moviesList = moviesList;
this.context=mContext;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recyclerview_list_items, parent, false);
MyViewHolder viewHolder = new MyViewHolder(v);
return viewHolder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
MovieData movieData = moviesList.get(position);
holder.person_name.setText(movieData.getGenre());
holder.person_photo.setImageResource(movieData.getPhoto());
holder.person_follow.setOnClickListener(clickListener);
holder.person_follow.setTag(holder);
}
View.OnClickListener clickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
if (v.getId() == R.id.btnfollow) {
isButtonClicked = !isButtonClicked; // toggle the boolean flag
v.setBackgroundResource(isButtonClicked ? R.drawable.following_img : R.drawable.follow_inactive);
}
}
};
#Override
public int getItemCount() {
return moviesList.size();
}
}
Clicking on holder.person_follow image button , image drawable bg is changing accordingly what i want but when i am scrolling the page at that time image drawable bg changing its position automatically. for ex. if i select the image button pos=1, after scrolling the page its changes the selected button position.
Instead of placing isButtonClicked in adapter class place it in MovieData modal class.Then make following changes in your adapter class:
public class SuggestionListItemAdapter extends RecyclerView.Adapter<SuggestionListItemAdapter.MyViewHolder> {
private List<MovieData> moviesList;
Context context;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView person_name;
ImageView person_photo;
ImageButton person_follow;
public MyViewHolder(View view) {
super(view);
person_photo = (ImageView) view.findViewById(R.id.person_photo);
person_name = (TextView) view.findViewById(R.id.person_name);
person_follow = (ImageButton) view.findViewById(R.id.btnfollow);
}
}
public SuggestionListItemAdapter(Context mContext,List<MovieData> moviesList) {
this.moviesList = moviesList;
this.context=mContext;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recyclerview_list_items, parent, false);
MyViewHolder viewHolder = new MyViewHolder(v);
return viewHolder;
}
#Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
final MovieData movieData = moviesList.get(position);
holder.person_name.setText(movieData.getGenre());
holder.person_photo.setImageResource(movieData.getPhoto());
holder.person_follow.setBackgroundResource(movieData.isButtonClicked() ? R.drawable.following_img : R.drawable.follow_inactive);
holder.person_follow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
movieData.setIsButtonClicked(!movieData.isButtonClicked());
holder.person_follow.setBackgroundResource(movieData.isButtonClicked() ? R.drawable.following_img : R.drawable.follow_inactive);
}
});
holder.person_follow.setTag(holder);
}
#Override
public int getItemCount() {
return moviesList.size();
}
}

How to draw directly to LinearLayout's canvas - Android

I have a LinearLayout with 3 ImageView s on it. Whenever the user clicks on an ImageView I want to draw a surrounding rectangle on the ImageView. I know how to draw something on a ImageView but I want to draw directly on the LinearLayout.
How can I do this?
I've already written the following code:
setContentView(R.id.anaekran2);
LinearLayout linLayout = (LinearLayout) findViewById(R.id.layout01);
Is there something like linLayout.getCanvas()?
I couldn't find a similiar function, but I've found
linLayout.getDrawingCache(). So,
Bitmap b = linLayout.getDrawingCache();
Canvas c = new Canvas(b); // this line gives an error, why?
You should create a custom linear layout. Overriding onDraw method of linear layout solves your problem. Here is the custom linear layout code.
public class CustomLinearLayout extends LinearLayout {
private Paint mPaint;
private int mClickedChild = -1;
public CustomLinearLayout(Context context) {
super(context);
setWillNotDraw(false);
createPaint();
}
public CustomLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(false);
createPaint();
}
public CustomLinearLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setWillNotDraw(false);
createPaint();
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
initializeChildrenClickEvent();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(mClickedChild != -1){
View child = getChildAt(mClickedChild);
canvas.drawRect(child.getLeft(), child.getTop(), child.getRight(), child.getBottom(), mPaint);
}
}
private void initializeChildrenClickEvent(){
final int childCount = getChildCount();
OnClickListener clickListener = new OnClickListener() {
#Override
public void onClick(View view) {
for(int i = 0; i < childCount; i++){
if(getChildAt(i).equals(view)){
mClickedChild = i;
break;
}
}
invalidate();
}
};
for(int i = 0; i < childCount; i++){
getChildAt(i).setOnClickListener(clickListener);
}
}
private void createPaint(){
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(5f);
}
}
And here is the usage of custom layout in xml.
<CustomLinearLayout
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"
android:gravity="center"
android:orientation="horizontal"
tools:context=".MainActivity">
<ImageView
android:id="#+id/image_view_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:src="#drawable/ic_launcher" />
<ImageView
android:id="#+id/image_view_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:src="#drawable/ic_launcher" />
<ImageView
android:id="#+id/image_view_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:src="#drawable/ic_launcher" />
</CustomLinearLayout>

Resources