lundi 1 octobre 2018

Android: Checking one CheckBox checks all CheckBoxes in the same row

My app shows a ListView with a different number of CheckBoxes for each row. The maxium number of CheckBoxes for a row is three. My app looks like this:

enter image description here

  1. If the left CheckBox gets checked, all CheckBoxes on the right side should get checked automatically.
  2. If the right CheckBox gets unchecked, all CheckBoxes on the left side should get unchecked automatically.

I´ll give a little example here:
There are three CheckBoxes (cb1, cb2 and cb3) in Row one. cb1 is on the left side, cb2 in the middle and cb3 on the right side.

  1. All CheckBoxes are currently unchecked. The user checks the left one (cb1). All other CheckBoxes (cb2 and cb3) are getting automatically checked.
  2. All CheckBoxes are currently checked. The user unchecks the right one (cb3). All other CheckBoxes (cb1 and cb2) are getting automatically unckecked.

I tried to solve my problem with OnCheckedChangeListener, but the following message occurs

"Variable 'Holder' is accessed from within the inner class, needs to be declared final."

My question:

  1. How to fix this, so that Message doesn´t occur?

  2. Is my solution logically right?

If my problem is not clear, pls leave a comment.

My solution:

 holder.cb1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                 @Override
                 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                     buttonView.setChecked(isChecked);
                     //Case1: Left (cb1) gets checked -> set all other right CB´s (cb2 & cb3) checked
                     if(isChecked){
                         holder.cb2.setChecked(isChecked);  //Error Message occurs here
                         holder.cb3.setChecked(isChecked);  //Error Message occurs here
                     }
                   }
               });

            holder.cb2.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    buttonView.setChecked(isChecked);
                    //Case2: Middle (cb2) gets checked -> set right CB (cb3) checked
                    if(isChecked){
                        holder.cb3.setChecked(isChecked);   //Error Message occurs here
                    }
                    //Case3: Middle (cb2) gets unchecked -> set left CB (cb1) unchecked
                    else {
                        holder.cb1.setChecked(isChecked);   //Error Message occurs here
                    }
                  }
              });

            holder.cb3.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    buttonView.setChecked(isChecked);
                    //Case4: Right (cb3) gets unchecked -> set all other left CB´s (cb1 & cb 2) unchecked
                    if(!isChecked){
                        holder.cb2.setChecked(isChecked);   //Error Message occurs here
                        holder.cb1.setChecked(isChecked);   //Error Message occurs here
                    }
                  }
              });

Custom Adapter:

public class ItemListAdapter extends BaseAdapter {

private LayoutInflater inflater;
private ArrayList<Object> itemArray;
int resIdImage;
private static final int TYPE_ListElement = 0;
private static final int TYPE_DIVIDER = 1;

public ItemListAdapter(Context context, ArrayList<Object> itemArray, int resource) {
    this.itemArray = itemArray;
    this.resIdImage = resource;
    this.inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public int getCount() {
    return itemArray.size();
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public Object getItem(int position) {
    return itemArray.get(position);
}

@Override
public int getViewTypeCount() {
    // TYPE_PERSON and TYPE_DIVIDER
    return 2;
}

@Override
public int getItemViewType(int position) {
    if (getItem(position) instanceof ItemList) {
        return TYPE_ListElement;
    }

    return TYPE_DIVIDER;
}

@Override
public boolean isEnabled(int position) {
    return (getItemViewType(position) == TYPE_ListElement);
}

public class DataHolder{
    ImageView imageView;
    TextView textView;
    CheckBox cb1;
    CheckBox cb2;
    CheckBox cb3;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {

    DataHolder holder =  null;
    int type = getItemViewType(position);
    if (convertView == null) {
        switch (type) {
            case TYPE_ListElement:
                convertView = inflater.inflate(resIdImage, parent, false);
                holder = new DataHolder();
                holder.imageView = (ImageView) convertView.findViewById(R.id.image);
                holder.textView = (TextView) convertView.findViewById(R.id.nameLabel);
                holder.cb1 = (CheckBox) convertView.findViewById(R.id.checkbox);
                holder.cb2 = (CheckBox) convertView.findViewById(R.id.checkbox2);
                holder.cb3 = (CheckBox) convertView.findViewById(R.id.checkbox3);
                convertView.setTag(holder);
                break;
            case TYPE_DIVIDER:
                convertView = inflater.inflate(R.layout.row_header, parent, false);
                break;
        }
    }
    else {
        holder = (DataHolder)convertView.getTag();
    }

    switch (type) {
        case TYPE_ListElement:
            ItemList item = (ItemList) getItem(position);
            holder.textView.setText(item.getTitle());
            holder.imageView.setImageResource(item.resIdImage);

            int numCheckBox = item.numCheckBox;
            if(numCheckBox == 1){
               holder.cb1.setVisibility(View.VISIBLE);
               holder.cb2.setVisibility(View.GONE);
               holder.cb3.setVisibility(View.GONE);
            } else if (numCheckBox == 2){
               holder.cb1.setVisibility(View.VISIBLE);
               holder.cb2.setVisibility(View.VISIBLE);
               holder.cb3.setVisibility(View.GONE);
            } else if (numCheckBox == 3){
               holder.cb1.setVisibility(View.VISIBLE);
               holder.cb2.setVisibility(View.VISIBLE);
               holder.cb3.setVisibility(View.VISIBLE);
            }
             holder.cb1.setChecked(item.checked);
             holder.cb2.setChecked(item.checked);
             holder.cb3.setChecked(item.checked);

             holder.cb1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                 @Override
                 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                     buttonView.setChecked(isChecked);
                     //Case1: Left (cb1) gets checked -> set all other right CB´s (cb2 & cb3) checked
                     if(isChecked){
                         holder.cb2.setChecked(isChecked);  //Error Message occurs here
                         holder.cb3.setChecked(isChecked);  //Error Message occurs here
                     }
                 }
             });

            holder.cb2.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    buttonView.setChecked(isChecked);
                    //Case2: Middle (cb2) gets checked -> set right CB (cb3) checked
                    if(isChecked){
                        holder.cb3.setChecked(isChecked);   //Error Message occurs here
                    }
                    //Case3: Middle (cb2) gets unchecked -> set left CB (cb1) unchecked
                    else {
                        holder.cb1.setChecked(isChecked);   //Error Message occurs here
                    }
                }
            });

            holder.cb3.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    buttonView.setChecked(isChecked);
                    //Case4: Right (cb3) gets unchecked -> set all other left CB´s (cb1 & cb 2) unchecked
                    if(!isChecked){
                        holder.cb2.setChecked(isChecked);   //Error Message occurs here
                        holder.cb1.setChecked(isChecked);   //Error Message occurs here
                    }
                }
            });

             break;

        case TYPE_DIVIDER:
            TextView title = (TextView)convertView.findViewById(R.id.headerTitle);
            String titleString = (String)getItem(position);
            title.setText(titleString);
            break;
    }


    return convertView;
}
}

Row Layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<ImageView
    android:id="@+id/image"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@mipmap/ic_launcher"
    android:layout_gravity="center"
    android:layout_margin="20dp"/>

<TextView
    android:id="@+id/nameLabel"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="20sp"
    android:layout_margin="20dp"
    android:text="Name"
    android:layout_weight="1"
/>

<CheckBox
    android:id="@+id/checkbox"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:checked="false"
    android:focusable="false"
    android:focusableInTouchMode="false"
    android:layout_gravity="right|center"
    android:gravity="right|center"
    />

<CheckBox
    android:id="@+id/checkbox2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:checked="false"
    android:focusable="false"
    android:focusableInTouchMode="false"
    android:layout_gravity="right|center"
    android:gravity="right|center"
    />

<CheckBox
    android:id="@+id/checkbox3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:checked="false"
    android:focusable="false"
    android:focusableInTouchMode="false"
    android:layout_gravity="right|center"
    android:gravity="right|center"
    />

</LinearLayout>




save and load Checkbox status across multiple devices

I am currently working on a project where I have to create a "website" that will only be launched on the intranet server of a company. So there is a user interface with 5 checkbox on it. Currently I am storing the checkbox status in the local storage like this:

<script>
var checkboxValues = JSON.parse(localStorage.getItem('checkboxValues')) || {},
    $checkboxes = $("#checkbox-container :checkbox");

        console.log(checkboxValues);
                
$checkboxes.on("change", function(){
  $checkboxes.each(function(){
    checkboxValues[this.id] = this.checked;
  });
  
  localStorage.setItem("checkboxValues", JSON.stringify(checkboxValues));
});

// On page load
$.each(checkboxValues, function(key, value) {
  $("#" + key).prop('checked', value);
});
</script>

This works fine so far! However now the problem I am struggling with for almost a week now:

The checkbox status have to be the same on every device... e.g if I am ticking a checkbox from one device the checkbox needs to be ticked by the next f5 on all other devices... I hope you guys can help me out and have some alternatives to store the checkbox status.

Thank you very much !

All the best

poza




Using chrome.storage.sync to save checkbox state

I am struggling to save the state of multiple checkboxes with the chrome.storage.sync. Checkboxes should keep being checked/unchecked after page refresh. My current code looks like this:

<script>
var checkboxValues = JSON.parse(chrome.storage.sync.get('checkboxValues')) || {},
    $checkboxes = $("#checkbox-container :checkbox");

        console.log(checkboxValues);
                
$checkboxes.on("change", function(){
  $checkboxes.each(function(){
    checkboxValues[this.id] = this.checked;
  });
  
chrome.storage.sync.set("checkboxValues", JSON.stringify(checkboxValues));
});

// On page load
$.each(checkboxValues, function(key, value) {
  $("#" + key).prop('checked', value);
});

copy(JSON.stringify(JSON.stringify(chrome.storage.sync)));

</script>

its not saving the state of the checkboxes and I always get the error:"Uncaught TypeError: Cannot read property 'sync' of undefined" even if I added the "storage" permission to my manifest.json

really need your help guys :D every suggestion is highly appreciated!




Send checkbox data (with label) to MFMailComposeViewController

I want to ask a question about best way to use of checkbox at swift. I have a view, which has four checkboxes and independent labels.

What is the best way to take that label data to send an email if checked? if does not, I want to send N/A. at mail.

I want to pass checked labels data to MFMailComposer. Here is my sample code, any help would be appreciable.

    import MessageUI

class DailyTasksViewController: UIViewController, MFMailComposeViewControllerDelegate {

@IBOutlet weak var dailyTaskOne: UILabel!
@IBOutlet weak var dailyTaskTwo: UILabel!
@IBOutlet weak var dailyTaskThree: UILabel!
@IBOutlet weak var dailyTaskFour: UILabel!

var mailComposer: MFMailComposeViewController = MFMailComposeViewController()

override func viewDidLoad() {
    super.viewDidLoad()
    addCheckboxSubviews()
}

func addCheckboxSubviews() {   
    // tick1
    let tickBox1 = Checkbox(frame: CGRect(x: 16, y: 110, width: 29, height: 28))
    tickBox1.borderStyle = .square
    tickBox1.borderWidth = 5
    tickBox1.checkmarkStyle = .tick
    tickBox1.checkmarkSize = 0.7
    tickBox1.uncheckedBorderColor = UIColor ( red: CGFloat(234/255.0), green: CGFloat(100/255.0), blue: CGFloat(76/255.0), alpha: CGFloat(1.0) )
    tickBox1.checkedBorderColor = UIColor ( red: CGFloat(194/255.0), green: CGFloat(57/255.0), blue: CGFloat(32/255.0), alpha: CGFloat(1.0) )
    tickBox1.checkmarkColor = UIColor ( red: CGFloat(255/255.0), green: CGFloat(255/255.0), blue: CGFloat(255/255.0), alpha: CGFloat(1.0) )
    tickBox1.checkboxBackgroundColor = UIColor ( red: CGFloat(234/255.0), green: CGFloat(100/255.0), blue: CGFloat(76/255.0), alpha: CGFloat(1.0) )
    tickBox1.addTarget(self, action: #selector(tickBox1ValueChanged(sender:)), for: .valueChanged)
    view.addSubview(tickBox1)

    // tick2
    let tickBox2 = Checkbox(frame: CGRect(x: 16, y: 168, width: 29, height: 28))
    tickBox2.borderStyle = .square
    tickBox2.borderWidth = 5
    tickBox2.checkmarkStyle = .tick
    tickBox2.checkmarkSize = 0.7
    tickBox2.uncheckedBorderColor = UIColor ( red: CGFloat(234/255.0), green: CGFloat(100/255.0), blue: CGFloat(76/255.0), alpha: CGFloat(1.0) )
    tickBox2.checkedBorderColor = UIColor ( red: CGFloat(194/255.0), green: CGFloat(57/255.0), blue: CGFloat(32/255.0), alpha: CGFloat(1.0) )
    tickBox2.checkmarkColor = UIColor ( red: CGFloat(255/255.0), green: CGFloat(255/255.0), blue: CGFloat(255/255.0), alpha: CGFloat(1.0) )
    tickBox2.checkboxBackgroundColor = UIColor ( red: CGFloat(234/255.0), green: CGFloat(100/255.0), blue: CGFloat(76/255.0), alpha: CGFloat(1.0) )
    tickBox2.addTarget(self, action: #selector(tickBox2ValueChanged(sender:)), for: .valueChanged)
    view.addSubview(tickBox2)

    // tick3
    let tickBox3 = Checkbox(frame: CGRect(x: 16, y: 226, width: 29, height: 28))
    tickBox3.borderStyle = .square
    tickBox3.borderWidth = 5
    tickBox3.checkmarkStyle = .tick
    tickBox3.checkmarkSize = 0.7
    tickBox3.uncheckedBorderColor = UIColor ( red: CGFloat(234/255.0), green: CGFloat(100/255.0), blue: CGFloat(76/255.0), alpha: CGFloat(1.0) )
    tickBox3.checkedBorderColor = UIColor ( red: CGFloat(194/255.0), green: CGFloat(57/255.0), blue: CGFloat(32/255.0), alpha: CGFloat(1.0) )
    tickBox3.checkmarkColor = UIColor ( red: CGFloat(255/255.0), green: CGFloat(255/255.0), blue: CGFloat(255/255.0), alpha: CGFloat(1.0) )
    tickBox3.checkboxBackgroundColor = UIColor ( red: CGFloat(234/255.0), green: CGFloat(100/255.0), blue: CGFloat(76/255.0), alpha: CGFloat(1.0) )
    tickBox3.addTarget(self, action: #selector(tickBox3ValueChanged(sender:)), for: .valueChanged)
    view.addSubview(tickBox3)

    // tick4
    let tickBox4 = Checkbox(frame: CGRect(x: 16, y: 284, width: 29, height: 28))
    tickBox4.borderStyle = .square
    tickBox4.borderWidth = 5
    tickBox4.checkmarkStyle = .tick
    tickBox4.checkmarkSize = 0.7
    tickBox4.uncheckedBorderColor = UIColor ( red: CGFloat(234/255.0), green: CGFloat(100/255.0), blue: CGFloat(76/255.0), alpha: CGFloat(1.0) )
    tickBox4.checkedBorderColor = UIColor ( red: CGFloat(194/255.0), green: CGFloat(57/255.0), blue: CGFloat(32/255.0), alpha: CGFloat(1.0) )
    tickBox4.checkmarkColor = UIColor ( red: CGFloat(255/255.0), green: CGFloat(255/255.0), blue: CGFloat(255/255.0), alpha: CGFloat(1.0) )
    tickBox4.checkboxBackgroundColor = UIColor ( red: CGFloat(234/255.0), green: CGFloat(100/255.0), blue: CGFloat(76/255.0), alpha: CGFloat(1.0) )
    tickBox4.addTarget(self, action: #selector(tickBox4ValueChanged(sender:)), for: .valueChanged)
    view.addSubview(tickBox4)
}

// target action example
@objc func tickBox1ValueChanged(sender: Checkbox) {
    //print("Tick box value change: \(sender.isChecked)")
    //print(dailyTaskOne.text as Any, (sender.isChecked))

    if sender.isChecked == true {
        print("ok")
    } else {
        print("nah")
    }
}

@objc func tickBox2ValueChanged(sender: Checkbox) {
    //print("Tick box value change: \(sender.isChecked)")
}

@objc func tickBox3ValueChanged(sender: Checkbox) {
    //print("Tick box value change: \(sender.isChecked)")
}

@objc func tickBox4ValueChanged(sender: Checkbox) {
    //print("Tick box value change: \(sender.isChecked)")
}

@IBAction func sendEmailClicked(_ sender: AnyObject) {

    let dateString: String = DateFormatter.localizedString(from: Date(), dateStyle: .short, timeStyle: .short)

    mailComposer = MFMailComposeViewController()
    mailComposer.mailComposeDelegate = self

    mailComposer.setToRecipients(["acme@mail.com"])
    mailComposer.setSubject("\(dateString) Daily email")
    mailComposer.setMessageBody("lorem ipsum dolor sit amet.",  isHTML: true)

    self.present(mailComposer, animated: true) {}
}

}




Android update sum of value on each action made

I am doing an application where my textview updates itself immediately based on the checked checkbox and radio button. I have 3 hashmaps to store the values of each items:

    hashMap.put("chkCheese", 2.50);
    hashMap.put("chkPep", 3.50);
    hashMap.put("chkChick", 2.00);
    hashMap.put("chkBeef", 4.00);
    hashMap.put("chkBlackOlives", 2.00);
    hashMap.put("chkPine", 1.00);
    hashMap.put("chkMushroom", 1.00);

And this is my function to show items checked on change for my checkbox:

    private void checkEnoughAndMakeDisabled (CheckBox checkBoxes []) {
    int count = 0;
    for (CheckBox cb:checkBoxes) {
        cb.setEnabled(true);
        if (cb.isChecked()) {
            count++;
            toppingsSelection.add(cb);

        }
    }

    String text="";
    for (CheckBox items: toppingsSelection) {
        text = text + items.getText().toString() + ", ";
    }
    toppings.setText(text);

    if (count >= 5) {
        for (CheckBox cb:checkBoxes) {
            if (!cb.isChecked()) {
                cb.setEnabled(false);
            }
        }
    }
    toppingsSelection.clear();
}

Calling my function in onCreate():

        //Display TOPPINGS text on each action made
    final CompoundButton.OnCheckedChangeListener chgListener = new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
            checkEnoughAndMakeDisabled(checkBox);
        }
    };

    for (CheckBox tmpCheckBox: checkBox) {

        tmpCheckBox.setOnCheckedChangeListener(chgListener);
    }

So far i can only show the name of items checked. I tried to do the similar stuff for my TextView priceSum to show the total sum but it doesnt work. I also tried putting the calculation and hashmap tag retrieval inside the checkEnoughAndMakeDisabled function, it crashes. How do you think is the best approach of getting the hashmap's value and do the calculation? My attemp:

       //Display PRICE text on each action made
    price.setOnEditorActionListener(new TextView.OnEditorActionListener() {
        @Override
        public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
            double cal=0.0;
            for (int y=0;y<checkBox.length;y++) {
                if (checkBox[y].isChecked()) {
                    toppingsSelection.add(checkBox[y]);
                }
            }
            for (CheckBox tmpTopping:toppingsSelection) {
                double toppingPriceSum = hashMap.get(tmpTopping.getTag());
                cal = cal + toppingPriceSum;
                String s = "RM " + toppingPriceSum;
                price.setText(s);
            }
            return false;
        }
    });




onchange for checkbox that hide/shows table column causes Edge to refresh

I have a Javascript function that hide/shows table columns through a checkbox onchange. It works fine on all browsers (inc. IE and IE emulating Edge) except for Edge where it causes the page to refresh, or displays "This page is having a problem loading".

This occurs when the checkbox is unticked and will show a table column again. It doesn't occur when the checkbox is ticked and hides a column.

Does anyone have any idea why Edge would do this? Or has anyone had a similar problem with Edge refreshing/crashing when rearranging/modifying tables.




Andoid: Store CheckBox state in CheckList for different days

My app is a simple checklist. If I click a checkbox and close the app, the checkbox state will be saved and reloaded when restarting. But now I want to add a calendar that can be used to pick a date. For each new day the default state of the checkboxes in the list should be unchecked. If the state of the checkbox changes it should be saved for this specific date. So if I close the app and choose the same day again the checkbox states should be reloaded. So how do I save the checkbox state dependent on the date and dependent on which checkbox is clicked in the listview? And can I still do this with sharedPreferences? Or should I use SQLite, because one year of usage would result in 3650 saved checkbox states (assuming my checklist contains around 10 items).