I'll use a ListView as navigation menu. So I found out how to add an ImageView next to the ListCell title using ListView.setCellFactory. But now I want to have more space between ImageView and title. How can I achieve this?
This is my code:
lvNavigation.setCellFactory(listView -> new ListCell<String>(){
private ImageView imageView = new ImageView();
#Override
public void updateItem(String name, boolean empty) {
super.updateItem(name, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
Image image = getImageFromStatus(name);
imageView.setImage(image);
setText(name);
setGraphic(imageView);
}
}
});
getImageFromStatus(name) returns an Image object.
Thats how it actually looks like:
Use the graphicTextGapProperty :
setGraphicTextGap(10.0); // Or any other appropriate value
Related
I realized that, even though the Sharedprefs, saves the checkbox state, it doesn't keep the drawable resource background thingy that way...... any way to save that too? I was hoping it stays like the picture below. EDIT : So my objective would be that, On checkbox being checked, background changes, because of sharedprefs, the checked state is saved and on exiting the app, the checkbox remains checked but the background of the checkbox returns to its "un-highlighted" state without the drawable background
CheckBox C1,C2,C3;
//Creating keys for sharedpreference
private static final String C1key = "C1_key";
private static final String C2key = "C2_key";
private static final String C3key = "C3_key";
SharedPreferences shp = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_anime);
//sharedpreference created with the name as anime
shp = getSharedPreferences("Anime",MODE_PRIVATE);
//This is just background gradient animation
ConstraintLayout constraintLayout = findViewById(R.id.layout_anime);
AnimationDrawable animationDrawable = (AnimationDrawable) constraintLayout.getBackground();
animationDrawable.setEnterFadeDuration(2000);
animationDrawable.setExitFadeDuration(4000);
animationDrawable.start();
//Initializing checkboxes
C1 = findViewById(R.id.C1);
C2 = findViewById(R.id.C2);
C3 = findViewById(R.id.C3);
//mapping checkbox and string for ease of use during sharedprefs
Map<String, CheckBox> checkBoxMap = new HashMap();
checkBoxMap.put(C1key,C1);
checkBoxMap.put(C2key,C2);
checkBoxMap.put(C3key,C3);
//loading initial values from sharedprefs, and also creating onCheckedChangeListeners from the map
loadInitialValues(checkBoxMap);
setupCheckedChangeListener(checkBoxMap);
}
public void loadInitialValues(Map<String, CheckBox> checkboxMap) {
for (Map.Entry<String, CheckBox> checkboxEntry: checkboxMap.entrySet()) {
boolean checked = shp.getBoolean(checkboxEntry.getKey(), false);
checkboxEntry.getValue().setChecked(checked);
}
}
public void setupCheckedChangeListener(Map<String, CheckBox> checkboxMap) { //for loop to cover all the checkboxes and keys in the map
for (final Map.Entry<String, CheckBox> checkboxEntry: checkboxMap.entrySet()) {
checkboxEntry.getValue().setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
final SharedPreferences.Editor editor = shp.edit();
editor.putBoolean(checkboxEntry.getKey(), isChecked);
editor.apply();
// this part is to turn the background of the checkbox to a specified drawable when its checked and when it isn't
if(checkboxEntry.getValue().isChecked()) //checkboxentry.getvalue().ischecked is to check whether specific checkboxes are in the checked state or not, Ex C1.ischecked() C2.ischecked() and so on
{
checkboxEntry.getValue().setBackgroundResource(R.drawable.cb_background);
}
else
{
checkboxEntry.getValue().setBackgroundResource(R.drawable.cb_background_default);
}
}
});
}
Than i believe should be something like this:
//If is selected set the background
if (C1.isChecked()) {
C1.setSelected(true);
C1.setBackgroundResource(R.drawable.[name of the background]);
}else{
//If is not selected
C1.setBackgroundResource(0);
}
Thanks to Suehtam for helping me out with this really appreciate it!!! this the solution
private void loadInitialValues(Map<String, CheckBox> checkboxMap) {
for (Map.Entry<String, CheckBox> checkboxEntry: checkboxMap.entrySet()) {
boolean checked = shp.getBoolean(checkboxEntry.getKey(), false);
checkboxEntry.getValue().setChecked(checked);
if (checkboxEntry.getValue().isChecked()) {
checkboxEntry.getValue().setSelected(true);
checkboxEntry.getValue().setBackgroundResource(R.drawable.cb_background);
}else{
//If is not selected
checkboxEntry.getValue().setBackgroundResource(0);
}
}
}
private void setupCheckedChangeListener(Map<String, CheckBox> checkboxMap) {
for (final Map.Entry<String, CheckBox> checkboxEntry: checkboxMap.entrySet()) {
checkboxEntry.getValue().setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
final SharedPreferences.Editor editor = shp.edit();
editor.putBoolean(checkboxEntry.getKey(), isChecked);
if (checkboxEntry.getValue().isChecked()) {
checkboxEntry.getValue().setSelected(true);
checkboxEntry.getValue().setBackgroundResource(R.drawable.cb_background);
}else{
//If is not selected
checkboxEntry.getValue().setBackgroundResource(0);
}
editor.apply();
}
});
}
}
Humm, if i understood what you want to do is not to save the value but instead to set the box selected.
something like this:
if(C1.isChecked()){
//In this way the box would be with the selected view.
C1.setSelected(true)
}
if is not the state selected and is just the drawable you could do the same:
It's just an example since i don't know which drawable function you are going to use.
Ex:
if(C1.isChecked()){
C1.setCheckMarkDrawable([drawable location]);
}
I'm trying to call event.getSource().getGraphic() in a branch expanded event of a TreeItem so that I can set a different icon, but I keep getting NullPointerException, and I can't figure out why. I can set the icon successfully when setting up the cell factory, but when I listen for the branch expanded event to do the same, it doesn't work. Here's how I'm setting up the tree (from the initialize event in my controller):
tree.setCellFactory(param -> new TreeCell<File>() {
#Override
public void updateItem(File item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText("");
setGraphic(null);
} else {
setText(item.getName());
Image icon = new Image(getClass().getResourceAsStream("folder.png"));
setGraphic(new ImageView(icon));
}
}
});
This works fine and dandy.
Here's my event listener where the ImageView is null for some reason (also being added in the initialize event in my TreeView controller):
File home = new File(System.getProperty("user.home"));
TreeItem<File> root = new TreeItem<>(home);
tree.setRoot(root);
root.addEventHandler(TreeItem.branchExpandedEvent(), event -> {
TreeItem source = event.getSource();
ImageView img = (ImageView)source.getGraphic(); // this is null!
Image icon = Image(getClass().getResourceAsStream("folder-open.png"));
img.setImage(icon);
});
Does anyone have any idea what I'm doing wrong? I'm using Java 1.8.
You're accessing the graphic property of the TreeItem, not the graphic property of the TreeCell that is set to a value != null. You need to handle this in the TreeCell instead. Furthermore you probably should use the disclosureNode property to replace the arrow. Also it's better to reuse the Images:
final Image closedImage = new Image(getClass().getResourceAsStream("folder.png"));
final Image openImage = new Image(getClass().getResourceAsStream("folder-open.png"));
tree.setCellFactory(param -> new TreeCell<File>() {
{
final ImageView imageView = new ImageView();
imageView.setFitWidth(20);
imageView.setFitHeight(20);
final ChangeListener<Boolean> expansionListener = new WeakChangeListener<>((o, oldValue, newValue) -> {
imageView.setImage(newValue ? openImage : closedImage);
});
// add change listener to expanded property of item
treeItemProperty().addListener((o, oldValue, newValue) -> {
if (oldValue != null) {
oldValue.expandedProperty().removeListener(expansionListener);
}
if (newValue != null) {
newValue.expandedProperty().addListener(expansionListener);
expansionListener.changed(null, null, newValue.isExpanded()); // trigger for initial value
}
});
setDisclosureNode(imageView);
}
#Override
public void updateItem(File item, boolean empty) {
super.updateItem(item, empty);
setText((empty || item == null) ? "" : item.getName());
}
});
if(myImageView.getDrawable() == null) {
return false;
}
else {
return true;
}
This tells if an image is attached with ImageView or not. I want to compare the Image which is residing in Drawable and Image which attached with ImageView.
private static final int WHITE_PAWN=R.drawable.wp,BLACK_PAWN=R.drawable.bp;
mSetOnClickListener(i,j,chess_array[i][j]);
protected void mSetOnClickListener(final int i,final int j,ImageView v){
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(isTroop(i,j)){
//for Events on ImageView
view.setBackgroundColor(getResources().getColor(R.color.select_troops_color));
}
}
});
}
protected boolean isTroop(final int i,final int j){
Drawable d=getBaseContext().getDrawable(BLACK_PAWN);
if(chess_array[i][j].getDrawable()==d){
return true;
}
else{
return false;
}
}
I have tried like this
Drawable d = getContext().getDrawable(R.drawable.your_drawable);
if(d == imageView.getDrawable()){
return true;
}
There are two ways you can do this. First way is you can assign your imageview in your XML with a TAG attribute and use the TAG attribute to determine which image it is. Of course you are not comparing the image here but you are comparing the tag.
XML
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:tag="TEST"
android:src="#drawable/ic_launcher_background"/>
Java Class
imageView = findViewById(R.id.image);
if("TEST".equals(imageView.getTag())){
}
This will determine the image via the value of the TAG.
However, if you are determined to compare the image itself; then you'll need to convert the images into Bitmap and compare the bitmap against each other. Here's a example:-
imageView = findViewById(R.id.image);
final Bitmap myImage = ((BitmapDrawable)imageView.getDrawable()).getBitmap();
Drawable drawable = getResources().getDrawable(R.drawable.ic_launcher_background);
final Bitmap comparingImg = ((BitmapDrawable) drawable).getBitmap();
if(myImage.sameAs(comparingImg)){
}
else{
}
Let me know if you need further clarification or if I am wrong.
I'm trying to add an image to a tableView and went through several questions and answers and it still doesn't work.
The other fields in the tableView like name are loaded correctly.
Intelij tells me that updateItem is never used, which is probably why it doesn't work, but I have no idea how to debug this...
Here's what I got so far
#FXML private TableColumn<PlayerManager, Image> tableColumnType;
#FXML private void initialize(){
tableColumnType.setCellFactory(param -> {
//Set up the ImageView
final ImageView imageview = new ImageView();
imageview.setFitHeight(10);
imageview.setFitWidth(10);
///imageview.setImage(imageComputer); //uncommenting this places the image on all cells, even empty ones
//Set up the Table
TableCell<PlayerManager, Image> cell = new TableCell<PlayerManager, Image>() {
public void updateItem(PlayerManager item, boolean empty) {
if (item != null) { // choice of image is based on values from item, but it doesn't matter now
imageview.setImage(imageComputer);
}
}
};
// Attach the imageview to the cell
cell.setGraphic(imageview);
return cell;
});
}
The questions I went through are:
How to add an Image into a JavaFx TableView column
Display image in table
Inserting images into TableView rows - JavaFX
The signature of the updateItem method is wrong: it should be
public void updateItem(Image item, boolean empty) { /* ... */ }
If the compiler rejects the #Override annotation, then you know you are not defining the correct method. So you should use #Override and if you get a compile error, it is a signal that something is not right.
So you should be able to do
#FXML private TableColumn<PlayerManager, Image> tableColumnType;
#FXML private void initialize(){
tableColumnType.setCellFactory(param -> {
//Set up the ImageView
final ImageView imageview = new ImageView();
imageview.setFitHeight(10);
imageview.setFitWidth(10);
///imageview.setImage(imageComputer); //uncommenting this places the image on all cells, even empty ones
//Set up the Table
TableCell<PlayerManager, Image> cell = new TableCell<PlayerManager, Image>() {
#Override
public void updateItem(Image item, boolean empty) {
if (item != null) { // choice of image is based on values from item, but it doesn't matter now
imageview.setImage(imageComputer);
}
}
};
// Attach the imageview to the cell
cell.setGraphic(imageview);
return cell;
});
}
If your table cell needs to access the actual PlayerManager object, then you need to make the table column a TableColumn<PlayerManager, PlayerManager> and update the cellValueFactory (which you haven't shown) accordingly.
Finally, note that your updateItem(...) method needs to deal with all cases, including empty cells for which the item is null.
So you may need something like
#FXML private TableColumn<PlayerManager, PlayerManager> tableColumnType;
#FXML private void initialize(){
tableColumnType.setCellValueFactory(cellData -> new SimpleObjectProperty<PlayerManager>(cellData.getValue());
tableColumnType.setCellFactory(param -> {
//Set up the ImageView
final ImageView imageview = new ImageView();
imageview.setFitHeight(10);
imageview.setFitWidth(10);
///imageview.setImage(imageComputer); //uncommenting this places the image on all cells, even empty ones
//Set up the Table
TableCell<PlayerManager, PlayerManager> cell = new TableCell<PlayerManager, PlayerManager>() {
#Override
public void updateItem(PlayerManager item, boolean empty) {
if (item != null) { // choice of image is based on values from item, but it doesn't matter now
imageview.setImage(imageComputer);
} else {
imageView.setImage(null);
}
}
};
// Attach the imageview to the cell
cell.setGraphic(imageview);
return cell;
});
}
The signature of the updateItem() method is wrong.
Try to use:
#Override
protected void updateItem(Image item, boolean empty){
//your code
}
Edit:
I think you can solve your problem by also setting a CellValueFactory for your TableColumn:
tableColumnType.setCellValueFactory(
new Callback<CellDataFeatures<PlayerManager, Image>, ObservableValue<Image>(){
#Override
public ObservableValue<Image> call(
CellDataFeatures<PlayerManager, Image> param) {
return param.getValue().exampleMethod; /* Method of your PlayerManager which returns an Image as ObservableValue. To do so you could wrap it in an `ObjectProperty<Image>`*/
}
}
);
I am making use of recycler view. I have a layout that is highlighted in light red,this layout is included for each item in the recycler view. The light red layout is placed over the background image. I am using setTag method to identify the clicks of the buttons in red layout. That is working properly when i click i get the position. The problem is i want to change the image at specific position.
For example : Consider the heart button. I have set a tag on it like this.
heartButton = findViewById(id);
heartButton.setTag(position);
now i get the position by using the getTag method. But now i want to change the image of the heartButton at the a specific position. Is there something like
heartButton.getTag(position).setImageResouce(drawable);
If not how do i do this then.
use setBackgroundResource(R.drawable.XXX)
http://developer.android.com/reference/android/view/View.html#setBackgroundResource(int)
Proper way to do this is,
You have to keep the state of the heart button stored in the model(POJO) which is passed to custom adapter.
e.g.
class ModelListItem{
public static final int HEART=1,BROKEN_HEART=2;
int heartButtonState;
}
Now in onClick() of heart button, get that object from adapter using position,cosidering you have already figured it out on how to preserve position from heart button
ModelListItem item = (ModelListItem)adapter.getItem(position)
Change the state of heart button;
item.setHeartButtonState(ModelListItem.BROKEN_HEART);
adapter.notifyDatasetChanged();
You already know below explaination but just in case
To work this properly,in your getView methode of adapter you need to put the check on heartButtonState(); and use appropriate image resource.
getView(BOILERPLATE){
BOILERPLATE
switch(item.getheartButtonState()){
case ModelItemList.HEART:
heartbutton.setImageResource(heart_image);
break;
case ModelItemList.BROKEN_HEART:
heartbutton.setImageResource(broken_heart_image);
break;
}
I made a custom click listener and updated the like in the setter getter.But this works only when the view has been moved out of the view (i think it is the scrapeview)
The Setter Getter Class
public class DemoData {
int background;
boolean liked;
public DemoData(int background) {
this.background = background;
}
public int getBackground() {
return background;
}
// public void setBackground(int background) {
// this.background = background;
// }
public boolean isLiked() {
return liked;
}
public void setLiked(boolean liked) {
this.liked = liked;
}
}
The onBindViewHolder function of the recycler view
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
background = (ImageView) holder.view.findViewById(R.id.image);
layout = (LinearLayout) holder.view.findViewById(R.id.layout);
delete = (ImageView) layout.findViewById(R.id.delete);
lock = (ImageView) layout.findViewById(R.id.lock);
delete.setTag("delete_"+position);
lock.setTag("lock_"+position);
if(Constants.demoDatas.get(position).isLiked()){
delete.setImageResource(R.drawable.ic_launcher);
}
else{
delete.setImageResource(android.R.drawable.ic_delete);
}
delete.setOnClickListener(new CustomClickListener(position));
lock.setOnClickListener(new CustomClickListener(position));
}
The custom click listener is as below
public class CustomClickListener implements View.OnClickListener {
int position;
public CustomClickListener(int position) {
this.position = position;
}
#Override
public void onClick(View v) {
String tag = (String) v.getTag();
String identifier[] = tag.split("_");
// this line saves my state in the Setter Getter Class
Constants.demoDatas.get(position).setLiked(true);
}
}