Checkbox enable EditText in RecyclerView issue - android-edittext

I am working for quiz app project. I've got a RecyclerView, each of them contains TextView, two Checkbox and EditText. What I want is when i checked the second Checkbox it will enable the EditText. I have already make this work. but the problem is if I Checked the Checkbox and Type something in the EditText on the first row, when I scroll down some of the others are mirroring the EditText state even I am not Checked the Checkbox to enable EditText of that row.
here is my adapter code:
public class StudentAdapter extends RecyclerView.Adapter<StudentAdapter.StudentViewHolder> {
private LayoutInflater inflator;
private int status;
Typeface typeface;
List<Student> students = Collections.emptyList();
public StudentAdapter(Context context, List<Student> students, String Font) {
inflator = LayoutInflater.from(context);
this.students = students;
typeface = Typeface.createFromAsset(context.getAssets(), Font);
}
#Override
public StudentViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflator.inflate(R.layout.student_row, parent, false);
StudentViewHolder studentViewHolder = new StudentViewHolder(view);
return studentViewHolder;
}
#Override
public void onBindViewHolder(final StudentViewHolder holder, final int position) {
final Student currentStudent = students.get(position);
holder.studentName.setText(currentStudent.student);
holder.chbIllegal.setTag(students.get(position));
holder.editText.setTag(students.get(position));
holder.chbIllegal.setChecked(students.get(position).isSelected());
holder.chbIllegal.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CheckBox cb = (CheckBox) v;
final Student contact = (Student) cb.getTag();
contact.setSelected(cb.isChecked());
students.get(position).setSelected(cb.isChecked());
// this will enable editText if checkbox is checked
if (cb.isChecked()) {
holder.editText.setEnabled(true);
holder.editText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
String Illegal = holder.editText.getText().toString();
contact.setAgaints_rule(Illegal);
Log.d("GExam", currentStudent.student + " " + Illegal);
}
});
holder.chbIllegal.setOnClickListener(null);
holder.chbIllegal.setTag(students.get(position));
} else {
holder.editText.setEnabled(false);
}
}
});
if (currentStudent.getStatus() == 1) {
holder.chbPresent.setChecked(true);
} else if (currentStudent.getStatus() == 0) {
holder.chbPresent.setChecked(false);
}
}
#Override
public int getItemCount() {
return students.size();
}
class StudentViewHolder extends RecyclerView.ViewHolder {
TextView studentName;
CheckBox chbPresent, chbIllegal;
EditText editText;
public StudentViewHolder(View itemView) {
super(itemView);
studentName = (TextView) itemView.findViewById(R.id.StudentlistText);
this.studentName.setTypeface(typeface);
editText = (EditText) itemView.findViewById(R.id.edtAgaintsRule);
chbPresent = (CheckBox) itemView.findViewById(R.id.chbPresent);
// chbIllegal will handle the editText
chbIllegal = (CheckBox) itemView.findViewById(R.id.chbIllegal);
editText.setEnabled(false);
}
}
public List<Student> getStudentList() {
return students;
}
}
How can I only enable EditText of the row that checkbox is checked?

Finally I've been able to solve my problem by my teacher helped. what I have changed is I move the listener from onBindViewHolder to my ViewHolder class like this:
public class StudentAdapter extends RecyclerView.Adapter<StudentAdapter.StudentViewHolder> {
private LayoutInflater inflator;
private int status;
Typeface typeface;
List<Student> students = Collections.emptyList();
public StudentAdapter(Context context, List<Student> students, String Font) {
inflator = LayoutInflater.from(context);
this.students = students;
typeface = Typeface.createFromAsset(context.getAssets(), Font);
}
#Override
public StudentViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflator.inflate(R.layout.student_row, parent, false);
StudentViewHolder studentViewHolder = new StudentViewHolder(view);
return studentViewHolder;
}
#Override
public void onBindViewHolder(final StudentViewHolder holder, final int position) {
final Student currentStudent = students.get(position);
holder.studentName.setText(currentStudent.student);
holder.chbIllegal.setTag(students.get(position));
holder.editText.setTag(students.get(position));
holder.editText.setText(currentStudent.getAgaints_rule());
if (currentStudent.isSelected()) {
holder.editText.setEnabled(true);
}else{
holder.editText.setEnabled(false);
}
holder.chbIllegal.setChecked(students.get(position).isSelected());
if (currentStudent.getStatus() == 1) {
holder.chbPresent.setChecked(true);
} else if (currentStudent.getStatus() == 0) {
holder.chbPresent.setChecked(false);
}
}
#Override
public int getItemCount() {
return students.size();
}
class StudentViewHolder extends RecyclerView.ViewHolder {
TextView studentName;
CheckBox chbPresent, chbIllegal;
EditText editText;
public StudentViewHolder(View itemView) {
super(itemView);
studentName = (TextView) itemView.findViewById(R.id.StudentlistText);
this.studentName.setTypeface(typeface);
editText = (EditText) itemView.findViewById(R.id.edtAgaintsRule);
chbPresent = (CheckBox) itemView.findViewById(R.id.chbPresent);
chbIllegal = (CheckBox) itemView.findViewById(R.id.chbIllegal);
chbIllegal.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CheckBox cb = (CheckBox) v;
Student s = (Student) v.getTag();
Log.e("GExam", String.valueOf(cb.isChecked()));
s.setSelected(cb.isChecked());
StudentViewHolder.this.editText.setEnabled(cb.isChecked());
}
});
editText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
Student student = (Student) StudentViewHolder.this.editText.getTag();
student.setAgaints_rule(s.toString());
}
});
}
}
public List<Student> getStudentList() {
return students;
}
}

Related

Can't update Item from RecycleView using a Custom Adapter and Listener

I have an updateTask method which opens an alert dialog. I am trying to call this method through a listener in the onBindViewHolder function in my custom adapter.
However my alert dialog does not pop up and while debugging I found out that my update task method is not called.
Please help me understand why.
Thanks
Here is my customAdapter:
public class TasksAdapter extends RecyclerView.Adapter<TasksAdapter.TaskViewHolder> {
private ArrayList<Model> tasks;
private TaskUpdateListener listener;
TasksAdapter(ArrayList<Model> tasks,TaskUpdateListener listener) {
this.tasks = tasks;
this.listener = listener;
}
#Override
public TaskViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.retrieved_layout, parent, false);
return new TaskViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull TaskViewHolder holder, int position) {
Model task = tasks.get(position);
holder.setDate(task.getDate());
holder.setTask(task.getTask());
holder.setDesc(task.getDescription());
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String taskString = task.getTask();
String descString = task.getDescription();
listener.onTaskUpdate(task, position);
}
});
}
#Override
public int getItemCount() {
return tasks.size();
}
public static class TaskViewHolder extends RecyclerView.ViewHolder {
View mView;
public TaskViewHolder(#NonNull View itemView) {
super(itemView);
mView = itemView;
}
public void setTask(String task) {
TextView taskTextView = mView.findViewById(R.id.taskTv);
taskTextView.setText(task);
}
public void setDesc(String desc) {
TextView descTextView = mView.findViewById(R.id.descriptionTv);
descTextView.setText(desc);
}
public void setDate(String date) {
TextView dateTextView = mView.findViewById(R.id.dateTv);
}
}
public interface TaskUpdateListener {
void onTaskUpdate(Model model, int position);
}
}
And here is my HomeActivity:
public class HomeActivity extends AppCompatActivity {
private Toolbar toolbar;
private RecyclerView recyclerView;
private FloatingActionButton floatingActionButton;
private FirebaseDatabase database = FirebaseDatabase.getInstance();
private DatabaseReference userTasksRef;
private FirebaseAuth mAuth;
private FirebaseUser mUser;
private String onlineUserID;
private ProgressDialog loader;
private String key = "";
private String task;
private String description;
#Override
public void onBackPressed(){
new AlertDialog.Builder(this)
.setMessage("Are you sure you want exit ?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.setNegativeButton("No", null)
.show();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_home);
toolbar = findViewById(R.id.homeToolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle("Todo List App");
mAuth = FirebaseAuth.getInstance();
recyclerView = findViewById(R.id.recyclerView);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setReverseLayout(true);
linearLayoutManager.setStackFromEnd(true);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(linearLayoutManager);
loader = new ProgressDialog(this);
mUser = mAuth.getCurrentUser();
onlineUserID = mUser.getUid();
database = FirebaseDatabase.getInstance("https://todolist-bbccd-default-rtdb.europe-west1.firebasedatabase.app");
userTasksRef = database.getReference("users").child(onlineUserID).child("tasks");
floatingActionButton = findViewById(R.id.fab);
floatingActionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
addTask();
}
});
}
private void addTask() {
AlertDialog.Builder myDialog = new AlertDialog.Builder(this);
LayoutInflater inflater = LayoutInflater.from(this);
View myView = inflater.inflate(R.layout.input_file, null);
myDialog.setView(myView);
final AlertDialog dialog = myDialog.create();
dialog.setCancelable(false);
final EditText task = myView.findViewById(R.id.task);
final EditText description = myView.findViewById(R.id.description);
Button save = myView.findViewById(R.id.saveBtn);
Button cancel = myView.findViewById(R.id.CancelBtn);
cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String mTask = task.getText().toString().trim();
String mDescription = description.getText().toString().trim();
String id = userTasksRef.push().getKey();
String date = DateFormat.getDateInstance().format(new Date());
if (TextUtils.isEmpty(mTask)) {
task.setError("Task Required");
return;
}
if (TextUtils.isEmpty(mDescription)) {
description.setError("Description Required");
return;
} else {
loader.setMessage("Adding your data");
loader.setCanceledOnTouchOutside(false);
loader.show();
Model model = new Model(mTask, mDescription, id, date);
userTasksRef.child(id).setValue(model).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(HomeActivity.this, "Task has been inserted successfully", Toast.LENGTH_SHORT).show();
loader.dismiss();
} else {
String error = task.getException().toString();
Toast.makeText(HomeActivity.this, "Failed: " + error, Toast.LENGTH_SHORT).show();
loader.dismiss();
}
}
});
}
dialog.dismiss();
}
});
dialog.show();
}
#Override
protected void onStart() {
super.onStart();
ArrayList<Model> tasks = new ArrayList<>();
userTasksRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot taskSnapshot : dataSnapshot.getChildren()) {
Model task = taskSnapshot.getValue(Model.class);
tasks.add(task);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
// Handle errors here
}
});
TasksAdapter.TaskUpdateListener listener = new TasksAdapter.TaskUpdateListener() {
#Override
public void onTaskUpdate(Model model, int position) {
updateTask(model, position);
}
};
TasksAdapter adapter = new TasksAdapter(tasks, listener);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
public void updateTask(Model task, final int position ) {
AlertDialog.Builder myDialog = new AlertDialog.Builder(this);
LayoutInflater inflater = LayoutInflater.from(this);
View view = inflater.inflate(R.layout.update_data, null);
myDialog.setView(view);
final AlertDialog dialog = myDialog.create();
final EditText mTask = view.findViewById(R.id.mEditTextTask);
final EditText mDescription = view.findViewById(R.id.mEditTextDescription);
mTask.setText(task.getTask());
mTask.setSelection(task.getTask().length());
mDescription.setText(task.getDescription());
mDescription.setSelection(task.getDescription().length());
Button delButton = view.findViewById(R.id.btnDelete);
Button updateButton = view.findViewById(R.id.btnUpdate);
updateButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String tasktxt = mTask.getText().toString().trim();
String descriptiontxt = mDescription.getText().toString().trim();
String date = DateFormat.getDateInstance().format(new Date());
Model model = new Model(tasktxt, descriptiontxt, key, date);
userTasksRef.child(key).setValue(model).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()){
Toast.makeText(HomeActivity.this, "Data has been updated successfully", Toast.LENGTH_SHORT).show();
}else {
String err = task.getException().toString();
Toast.makeText(HomeActivity.this, "update failed "+err, Toast.LENGTH_SHORT).show();
}
}
});
dialog.dismiss();
}
});
}
}

how do I highlight the searched text using android search view Widget?

My search view is working properly but I am trying to do a search such that all the "visible" search letters should be highlighted. I used the filter interface in my adapter for filtering data.
here is my adapter Class
public class myAdapter extends RecyclerView.Adapter<myAdapter.viewHolder> implements Filterable {
private List<Model> model;
// for search filtering
private ArrayList<Model> modelFull;
Context context;
public myAdapter(ArrayList<Model> model, Context context) {
this.model = model;
modelFull =new ArrayList<>(model);
this.context = context;
}
#NonNull
#Override
public viewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.template, parent, false);
return new viewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull viewHolder holder, int position) {
Model forPosition = model.get(position);
holder.image.setImageResource(forPosition.getImage());
holder.intro.setText(forPosition.getIntro());
}
#Override
public int getItemCount() {
return model.size();
}
public class viewHolder extends RecyclerView.ViewHolder {
TextView intro;
ImageView image;
public viewHolder(#NonNull View itemView) {
super(itemView);
intro= itemView.findViewById(R.id.introTxt);
image = itemView.findViewById(R.id.image);
}
}
#Override
public Filter getFilter() {
return generalFilter;
}
private Filter generalFilter =new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
List<Model> filteredModel =new ArrayList<>();
if(constraint ==null || constraint.length()==0) {
filteredModel.addAll(modelFull);
}
else {
String searchQuery= constraint.toString().toLowerCase().trim();
for(blogBigModel item : modelFull){
if(item.getBlogIntro().toLowerCase().contains(searchQuery)){
filteredModel.add(item);
}
}
}
FilterResults results =new FilterResults();
results.values = filteredModel;
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
model.clear();
model.addAll((List)results.values);
notifyDataSetChanged();
}
};
}
that's my class / Fragment where i used the above adapter
[what should i add to get the desired highlighted query when i search in the search bar like Whatsapp][1]
[1]: https://i.stack.imgur.com/Fdu2r.jpg
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.ic_home_search:enter code here
SearchView searchView = (SearchView) item.getActionView();
searchView.setQueryHint("Search....");
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setBackground(getResources().getDrawable(R.drawable.searchview_bg));
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return false;
}
});
}
}
return true;
});

viewholder onclickListener null object reference

Attempt to invoke interface method 'void com.example.imovie.adapter.MovieItemClickListener.onMovieClick(com.example.imovie.models.Movie, android.widget.ImageView)' on a null object reference
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.MyViewHolder> {
Context context ;
List<Movie> mData;
MovieItemClickListener movieItemClickListener;
public MovieAdapter(Context context, List<Movie> mData, MovieItemClickListener listener) {
this.context = context;
this.mData = mData;
movieItemClickListener = listener;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(context).inflate(R.layout.item_movie,viewGroup,false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder myViewHolder, int i) {
myViewHolder.TvTitle.setText(mData.get(i).getTitle());
myViewHolder.ImgMovie.setImageResource(mData.get(i).getThumbnail());
}
#Override
public int getItemCount() {
return mData.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private TextView TvTitle;
private ImageView ImgMovie;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
TvTitle = itemView.findViewById(R.id.item_movie_title);
ImgMovie = itemView.findViewById(R.id.item_movie_img);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
movieItemClickListener.onMovieClick(mData.get(getAdapterPosition()),ImgMovie);//i have a null object reference
}
});
}
}
}
public class HomeFragment extends Fragment implements MovieItemClickListener {
private HomeViewModel homeViewModel;
private List<Slide> listSlides;
private ViewPager slidePager;
private TabLayout indicator;
private RecyclerView moviesRV;
private RecyclerView moviesRV2;
private MovieItemClickListener movieItemClickListener;
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
homeViewModel =
ViewModelProviders.of(this).get(HomeViewModel.class);
View root = inflater.inflate(R.layout.fragment_home, container, false);
slidePager = root.findViewById(R.id.slider_pager);
indicator = root.findViewById(R.id.indicator);
moviesRV = root.findViewById(R.id.rsViewMovies);
moviesRV2 = root.findViewById(R.id.rsViewMovies2);
iniSlider();
final SliderPagerAdapter sliderPagerAdapteradapter = new SliderPagerAdapter(getContext(), listSlides);
final MovieAdapter movieAdapter = new MovieAdapter(getContext(), DateSource.getPopularMovies(), movieItemClickListener);
final Timer timer = new Timer();
timer.scheduleAtFixedRate(new SliderTimer(), 4000, 6000);
homeViewModel.getText().observe(this, new Observer<String>() {
#Override
public void onChanged(#Nullable String s) {
slidePager.setAdapter(sliderPagerAdapteradapter);
indicator.setupWithViewPager(slidePager, true);
moviesRV.setAdapter(movieAdapter);
moviesRV.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
moviesRV2.setAdapter(movieAdapter);
moviesRV2.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
}
});
return root;
}
#Override
public void onMovieClick(Movie movie, ImageView imageView) {
Intent intent = new Intent(getContext(), MovieDetailActivity.class);
intent.putExtra("title", movie.getTitle());
intent.putExtra("imgURL", movie.getThumbnail());
intent.putExtra("imgCover", movie.getCoverPhoto());
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(getActivity(),
imageView, "sharedName");
startActivity(intent, options.toBundle());
Toast.makeText(getContext(), "item clicked : " + movie.getTitle(), Toast.LENGTH_LONG).show();
}
class SliderTimer extends TimerTask {
#Override
public void run() {
if (getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if (slidePager.getCurrentItem() < listSlides.size() - 1) {
slidePager.setCurrentItem(slidePager.getCurrentItem() + 1);
} else {
slidePager.setCurrentItem(0);
}
}
});
}
}
}
private void iniSlider() {
listSlides = new ArrayList<>();
listSlides.add(new Slide(R.drawable.a, "slide title \n movie title"));
listSlides.add(new Slide(R.drawable.b, "slide title"));
listSlides.add(new Slide(R.drawable.a, "slide title \n movie title"));
listSlides.add(new Slide(R.drawable.b, "slide title"));
}
}
If I'm not wrong, HomeFragment.movieItemClickListener is never initialized.
You may want to make the following changes in HomeFragment:
1. Delete the line
private MovieItemClickListener movieItemClickListener;
2. In this line
final MovieAdapter movieAdapter = new MovieAdapter(getContext(), DateSource.getPopularMovies(), movieItemClickListener);
change movieItemClickListener to this, because HomeFragment implements MovieItemClickListener.
That should fix the NullPointerException.

JavaFX TableView bold whole row iff `message.isUnread()==true`

I am trying to replicate Gmail behavior in Javafx TableView. Row of new Unread message should be shown in bold. Here is what I was able to do so far:
I can change background of the whole row, and bold a cell, but can't bold the whole row.
How to explain Javafx to do this?
for each Cell cell in tableview:
get Message m corresponding to row.
String style = m.isUnread() ? "
cell.setStyle("-fx-font-weight: 800" : "-fx-font-weight: 100")
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class Message {
final static public ObservableList<Message> data = FXCollections.observableArrayList(
new Message("Bob", "Where are you?", true, true),
new Message("Elise", "Payment", false, false),
new Message("Charlie", "Read this book: 'Clean code'", true, true),
new Message("Oscar", "Golf class tonight", true, false),
new Message("Sam", "How is your TableView progress?", false, true),
new Message("Alice", "Latte", true, true)
);
final private String name;
final private String title;
private boolean isUnread;
private boolean isArchived;
public Message(String name, String title, boolean isUnread, boolean isArchived) {
this.name = name; this.title = title; this.isUnread = isUnread;this.isArchived = isArchived;
}
public String getName() { return name; }
public String getTitle() { return title; }
public boolean getIsUnread() { return isUnread; }
public boolean getisArchived() { return isArchived; }
public void setIsUnread(boolean isUnread) { this.isUnread = isUnread; }
}
MyTable.java
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import javafx.util.Callback;
public class MyTable extends Application {
public static void main(String[] args) throws Exception { launch(args); }
public void start(final Stage stage) throws Exception {
stage.setTitle("Inbox");
// create a table.
TableView<Message> table = new TableView(Message.data);
table.getColumns().addAll(makeStringColumn("Name", "name", 150), makeStringColumn("Title", "title", 300), makeBooleanColumn("New", "isUnread", 150));
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
table.setPrefHeight(250);
stage.setScene(new Scene(table));
stage.getScene().getStylesheets().add(getClass().getResource("message.css").toExternalForm());
stage.show();
// highlight the table rows depending upon whether we expect to get paid.
int i = 0;
for (Node n: table.lookupAll("TableRow")) {
if (n instanceof TableRow) {
TableRow row = (TableRow) n;
if (table.getItems().get(i).getIsUnread()) {
row.getStyleClass().add("isReadRow");
} else {
row.getStyleClass().add("isUnreadRow");
}
i++;
if (i == table.getItems().size())
break;
}
}
}
private TableColumn<Message, String> makeStringColumn(String columnName, String propertyName, int prefWidth) {
TableColumn<Message, String> column = new TableColumn<>(columnName);
column.setCellValueFactory(new PropertyValueFactory<Message, String>(propertyName));
column.setCellFactory(new Callback<TableColumn<Message, String>, TableCell<Message, String>>() {
#Override public TableCell<Message, String> call(TableColumn<Message, String> soCalledFriendStringTableColumn) {
return new TableCell<Message, String>() {
#Override public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
setText(item);
}
}
};
}
});
column.setPrefWidth(prefWidth);
column.setSortable(false);
return column;
}
private TableColumn<Message, Boolean> makeBooleanColumn(String columnName, String propertyName, int prefWidth) {
TableColumn<Message, Boolean> column = new TableColumn<>(columnName);
column.setCellValueFactory(new PropertyValueFactory<Message, Boolean>(propertyName));
column.setCellFactory(new Callback<TableColumn<Message, Boolean>, TableCell<Message, Boolean>>() {
#Override public TableCell<Message, Boolean> call(TableColumn<Message, Boolean> soCalledFriendBooleanTableColumn) {
return new TableCell<Message, Boolean>() {
#Override public void updateItem(final Boolean item, final boolean empty) {
super.updateItem(item, empty);
if (item != null) {
setText(item.toString());
this.getStyleClass().add(item ? "isUnreadCell" : "isReadCell");
}
}
};
}
});
column.setPrefWidth(prefWidth);
column.setSortable(false);
return column;
}
}
(Message.css)
.column-header-background { -fx-background-color: azure; }
.isReadRow { -fx-background-color: palegreen; }
.isUnreadRow { -fx-background-color: yellow; }
.isReadCell { -fx-font-weight: 100 ; -fx-text-fill: darkgreen;}
.isUnreadCell { -fx-font-weight: 800 ; -fx-text-fill: red;}
To bold a row associate a RowFactory as shown below.
table.setPrefHeight(250);
table.setRowFactory(new Callback<TableView<Message>, TableRow<Message>>() {
#Override
public TableRow<Message> call(TableView<Message> param) {
final TableRow<Message> row = new TableRow<Message>() {
#Override
protected void updateItem(Message row, boolean empty) {
super.updateItem(row, empty);
if (!empty)
styleProperty().bind(Bindings.when(row.selectedProperty())
.then("-fx-font-weight: bold; -fx-font-size: 16;")
.otherwise(""));
}
};
return row;
}
});
stage.setScene(new Scene(table));
In the above sample, selectedProperty() function has been called by the Message row. The selectedProperty() function returns the value of boolean variable isUnread. If the isUnread value is true then the whole row will be bolded else it won't be.
final private String title;
private boolean isUnread;
private boolean isArchived;
private BooleanProperty selected;
public boolean getSelected() {return selected.get();}
public BooleanProperty selectedProperty(){return selected;}
public Message(String name, String title, boolean isUnread, boolean isArchived) {
this.name = name; this.title = title; this.isUnread = isUnread;this.isArchived = isArchived;
this.selected = new SimpleBooleanProperty(isUnread);
}
Setting the font style as bold and size to 16 gives following output:
I'd recommend using PseudoClasses to denote read/unread rows. Use a rowFactory to set the PseudoClasses. Also using a property for the read/unread state would be preferable, since this allows you to update the rows without refreshing the whole table:
private final BooleanProperty unread;
public void setUnread(boolean value) {
this.unread.set(value);
}
public boolean isUnread() {
return this.unread.get();
}
public BooleanProperty unreadProperty() {
return unread;
}
public Message(String name, String title, boolean isUnread, boolean isArchived) {
this.name = name;
this.title = title;
this.unread = new SimpleBooleanProperty(isUnread);
this.isArchived = isArchived;
}
final PseudoClass read = PseudoClass.getPseudoClass("read");
final PseudoClass unread = PseudoClass.getPseudoClass("unread");
table.setRowFactory(tv -> new TableRow<Message>() {
private void setState(boolean readState, boolean unreadState) {
pseudoClassStateChanged(unread, unreadState);
pseudoClassStateChanged(read, readState);
}
private void setUnreadState(boolean unreadState) {
setState(!unreadState, unreadState);
}
private final ChangeListener<Boolean> unreadListener = (observable, oldValue, newValue) -> setUnreadState(newValue);
#Override
protected void updateItem(Message item, boolean empty) {
// remove listener from old item
Message oldItem = getItem();
if (oldItem != null) {
oldItem.unreadProperty().removeListener(unreadListener);
}
super.updateItem(item, empty);
if (empty || item == null) {
setState(false, false);
} else {
// set appropriate state & add listener
setUnreadState(item.isUnread());
item.unreadProperty().addListener(unreadListener);
}
}
});
stage.setScene(new Scene(table));
.table-row-cell:read {
-fx-background-color: palegreen;
}
.table-row-cell:unread {
-fx-background-color: yellow;
}
.table-row-cell:read>.table-cell {
-fx-font-weight: 100;
-fx-text-fill: darkgreen;
}
.table-row-cell:unread>.table-cell {
-fx-font-weight: 800;
-fx-text-fill: red;
}
Also make sure to set the text of TableCells even if they become empty. Otherwise you could see "ghost content":
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
setText(item);
} else {
setText("");
}
}
#Override
public void updateItem(final Boolean item, final boolean empty) {
super.updateItem(item, empty);
if (item != null) {
setText(item.toString());
} else {
setText("");
}
}

Get field value from PopupScreen back to MainScreen in Blackberry

Now i have a MyScreen which extends from MainScreen containing a button. When the button clicked, it will show the PopupScreen containing list of RadioButtonFields, OK and Cancel buttons. My question is how to get RadioButtonField value from PopupScreen back to MyScreen.
Please help me in this case.
Thanks
Below is my code
MyScreen.java
public class MyScreen extends MainScreen{
private int currentValue = 0;
public MyScreen() {
LabelField lblField = new LabelField();
lblField.setText("Current Value = " + currentValue);
ButtonField btnPopup = new ButtonField("Show Popup");
btnPopup.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
UiApplication.getUiApplication().pushScreen(new MyPopupScreen());
}
});
add(lblField);
add(btnPopup);
}
}
MyPopupScreen
public class MyPopupScreen extends PopupScreen implements FieldChangeListener {
private int currentValue = -1;
public MyPopupScreen() {
super(new VerticalFieldManager(VerticalFieldManager.VERTICAL_SCROLL|VerticalFieldManager.VERTICAL_SCROLLBAR), Field.FOCUSABLE
);
add(new LabelField("Select Chart Type"));
RadioButtonGroup radioGroup = new RadioButtonGroup();
for (int i = 0; i < 10; i++) {
RadioButtonField radio = new RadioButtonField("Option no. " + i, radioGroup, false);
radio.setChangeListener(this);
add(radio);
}
ButtonField cancelBtn = new ButtonField("Close");
ButtonField okBtn = new ButtonField("OK");
add(okBtn);
add(cancelBtn);
cancelBtn.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
UiApplication.getUiApplication().popScreen();
}
});
okBtn.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
//How to get radio value or index value to pass back to MyScreen
}
});
}
public void fieldChanged(Field field, int context) {
if (field instanceof RadioButtonField) {
RadioButtonField radio = (RadioButtonField) field;
currentValue = radio.getIndex();
}
}
}
As Vijay, suggested this is one way that we could achieve this using inner class. The other approach could be, using design observer design patterns.
Try understanding the below code, and use what ever is efficient for you.
MyScreen.java
public class MyScreen extends MainScreen implements MyListener {
MyScreen screen = null;
public MyScreen() {
screen = this;
LabelField lblField = new LabelField();
lblField.setText("Current Value = " + currentValue);
ButtonField btnPopup = new ButtonField("Show Popup");
btnPopup.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
UiApplication.getUiApplication().pushScreen(new MyPopupScreen(screen));
}
});
add(lblField);
add(btnPopup);
}
public void valueChanged(int selectedIdx) {
Dialog.alert(selectedIdx );
}
}
MyListener.java
public interface MyListener {
public void valueChanged(int selectedIdx);
}
MyPopupScreen.java
public class MyPopupScreen extends PopupScreen implements FieldChangeListener {
MyScreen deligate = null;
public MyPopupScreen(final MyScreen deligate) {
super(new VerticalFieldManager(VerticalFieldManager.VERTICAL_SCROLL|VerticalFieldManager.VERTICAL_SCROLLBAR), Field.FOCUSABLE);
this.deligate = deligate;
add(new LabelField("Select Type"));
ButtonField closeBtn = new ButtonField("Close");
ButtonField okBtn = new ButtonField("OK");
add(okBtn);
add(closeBtn);
closeBtn.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
UiApplication.getUiApplication().popScreen(UiApplication.getUiApplication().getActiveScreen());
}
});
okBtn.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
deligate.valueChanged(radioGroup.getSelectedIndex());
UiApplication.getUiApplication().popScreen(UiApplication.getUiApplication().getActiveScreen());
}
});
}
}
public class MyScreen extends MainScreen{
private int currentValue = 0;
String result; // Declare the result
public MyScreen() {
LabelField lblField = new LabelField();
lblField.setText("Current Value = " + currentValue);
ButtonField btnPopup = new ButtonField("Show Popup");
btnPopup.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
UiApplication.getUiApplication().pushScreen(new MyPopupScreen());
}
});
ButtonField btnGetResult = new ButtonField("result"); //Add new Button
btnGetResult.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
Dialog.inform(result);
}
});
add(lblField);
add(btnPopup);
add(btnGetResult);// Add button to get the selected index
}
public class MyPopupScreen extends PopupScreen implements FieldChangeListener {
private int currentValue = -1;
RadioButtonField radio;
public MyPopupScreen() {
super(new VerticalFieldManager(VerticalFieldManager.VERTICAL_SCROLL|VerticalFieldManager.VERTICAL_SCROLLBAR), Field.FOCUSABLE
);
add(new LabelField("Select Chart Type"));
final RadioButtonGroup radioGroup = new RadioButtonGroup();
for (int i = 0; i < 10; i++) {
radio = new RadioButtonField("Option no. " + i, radioGroup, false);
radio.setChangeListener(this);
add(radio);
}
ButtonField cancelBtn = new ButtonField("Close");
ButtonField okBtn = new ButtonField("OK");
add(okBtn);
add(cancelBtn);
cancelBtn.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
UiApplication.getUiApplication().popScreen(MyPopupScreen.this);
}
});
okBtn.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
result = radioGroup.getSelectedIndex()+"";
UiApplication.getUiApplication().popScreen(MyPopupScreen.this);
}
});
}
public void fieldChanged(Field field, int context) {
if (field instanceof RadioButtonField) {
RadioButtonField radio = (RadioButtonField) field;
currentValue = radio.getIndex();
}
}
}
}

Resources