create checkboxes runtime and get values using DataBinding - android

Currently i am using DataBinding in my application and it is working like charm. Now i have a question, can we create multiple checkboxes based on API response?
like i have one ArrayList in my model class, and whatever is the size of that arraylist that much checkboxes should be added.
{"hobby": [
{
"id": "1",
"hobby": "Sports"
},
{
"id": "2",
"hobby": "Hangout"
},
{
"id": "3",
"hobby": "Skydiving"
},
{
"id": "4",
"hobby": "Scubadiving"
},
{
"id": "5",
"hobby": "Travelling"
}
]}
Now i want to create checkboxes of all hobbies and want to retrieve values of selected checkboxes.
Can anyone help me with this?
i have created BindingAdapter for this, and able to create checkboxes runtime
#BindingAdapter({"bind:values"})
public static void createCheckboxes(LinearLayout layout, UserModel model) {
List<UserModel.Hobby> list = model.getHobby();
for (int i = 0; i < list.size(); i++) {
CheckBox chk = new CheckBox(layout.getContext());
chk.setText(list.get(i).getHobby());
layout.addView(chk);
}
}
Now problem is how to get selected checkbox values.
Note : need to implement it with DataBinding.

Finally have done it, don't know whether it's correct use of databinding or not.
created binding method like this
#BindingAdapter({"bind:values"})
public static void createCheckboxes(LinearLayout layout, UserModel model) {
List<UserModel.Hobby> list = model.getHobby();
for (int i = 0; i < list.size(); i++) {
CheckBox chk = new CheckBox(layout.getContext());
chk.setText(list.get(i).getHobby());
final int finalI = i;
chk.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
UserModel.Hobby model=list.get(finalI);
if(model.isSelected())
model.setSelected(false);
else
model.setSelected(true);
list.set(finalI,model);
layout.invalidate();
}
});
layout.addView(chk);
}
}
and in my xml, created one LinearLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginLeft="15dp"
app:values="#{user}"/>
and while saving data, i am just checking with use of for loop and got which values are selected.
for (int i = 0; i < list.size(); i++) {
if(list.get(i).isSelected())
Log.e("", "selected: " + list.get(i).getHobby());
}

How about this :
LinearLayout root= (LinearLayout)findViewById(R.id.test);
// use loop
CheckBox checkBoxOne = new CheckBox(this);
root.addView(checkBoxOne);

Related

How to get a corresponding key in a json object and put it in my recyclerView onBindViewHolder

I have a json array, jsonArray, like:
[{
"phone_number": "+123456",
"name": "Bob"
},
{
"phone_number": "+234567",
"name": "Tom"
},
{
"phone_number": "+345678",
"name": "Jim"
},
{
"phone_number": "+4567890",
"name": "Jane"
},
{
"phone_number": "+5678901",
"name": "Sally"
}
]
In my onBindViewHolder I want to check if phone_number value in the json array matches username and then if there is a match then in the viewHolder.phone_user_name set the text to the corresponding value in "name" of the json array.
But all I get in my recyclerView for each cell is user : (blank)
Here's what I've tried so far:
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
SharedReview r = the_Shared_reviews.get(position);
//username is in fact a phone number from the db
String username = r.getUsername();
String phone_user_name = "";
int matching = jsonArray.length();
for (int i = 0; i < matching; i++) {
try {
JSONObject object = jsonArray.getJSONObject(i);
if (object.getString("phone_number").contains(username))
{
phone_user_name = (object.getString("name"));
}
} catch (JSONException e) {
Log.e("MYAPP", "unexpected JSON exception", e);
// Do something to recover ... or kill the app.
}
}
//I want to set the text to Bob, Tom, or whatever corresponding
// phone number matches username
((ReviewHolder) viewHolder).phone_user_name.setText("user :" + phone_user_name);
}
You should create a list of Object of (Phone Number, Name) and bind it to the recycler view. in "onBindViewHolder()", you can find the corresponding object from the list which contains both fields.
I'm not sure what value is supposed to be in the SharedReview class under the username variable, but I'm assuming it's a name, not a number.
However, you are testing if your json array item named "phone_number", which in your example is an actual phone number, contains the username. Which is assumably a name.
You should replace:
if (object.getString("phone_number").contains(username))
{
phone_user_name = (object.getString("name"));
}
With:
if (object.getString("name").equals(username))
{
phone_user_name = (object.getString("name"));
}

Rxjava zip operator filter second Observable by checking data with first Observable android

I am using .zip operator to combine 2 API calls
What I want
I wanted to get filtered values from 2nd Observable based on some ids from 1st Observable
Eg
1st Observable returns data like (sample data)
"categories": [
{
"category": "1",
"category_name": "Wedding Venues",
"category_photo_url": "http://www.marriager.com/uploads/album/0463373001465466151-0463467001465466151.jpeg",
"category_type_id": "1",
2nd Observable returns data like :
"data": [
{
"cat_id": "1",
"category_name": "Wedding Venues",
"status": "1",
"order_id": "1",
"category_type_id": "1"
},
I wanted to filter my 2nd Observable data to only return values that matches category_type_id from 1st Observable
My Code
Observable obsService = retrofitService.loadService(getSharedPref().getVendorId());
Observable obsCategory = retrofitService.loadCategory();
Observable<ServiceAndCategory> obsCombined = Observable.zip(obsService.observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()), obsCategory.observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()), new Func2<ServiceModel, CategoryModel, ServiceAndCategory>() {
#Override
public ServiceAndCategory call(ServiceModel serviceModel, CategoryModel categoryModel) {
return new ServiceAndCategory(serviceModel, categoryModel);
}
});
obsCombined.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io());
obsCombined.subscribe(new Subscriber<ServiceAndCategory>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
if (e instanceof UnknownHostException || e instanceof ConnectException) {
mPresenter.onNetworkError();
} else if (e instanceof SocketTimeoutException) {
mPresenter.onTimeOutError();
} else {
mPresenter.onServerError();
}
}
#Override
public void onNext(ServiceAndCategory model) {
mPresenter.onSuccess(model);
}
});
EDIT
basically I want to apppy the following logic
this.categoryList = combinedModel.categoryModel.getData();
serviceList = combinedModel.serviceModel.getData().getCategories();
for (int i = 0; i < serviceList.size(); i++) {
for (int j = 0; j < categoryList.size(); j++) {
if (!serviceList.get(i).getCategoryTypeId().equals(categoryList.get(j).getCategoryTypeId())) {
categoryList.remove(j);
}
}
}
You can apply this filtering with reactive approach using a map and a list, first collect all categories to a map, and all services to a list, zip them together, and then filter the services list according to categories map:
Observable<HashMap<Integer, CategoryData>> categoriesMapObservable =
obsCategory
.flatMapIterable(CategoryModel::getData)
.reduce(new HashMap<>(),
(map, categoryData) -> {
map.put(categoryData.getCategoryTypeId(), categoryData);
return map;
}
);
Observable<List<ServiceData>> serviceListObservable = obsService
.map(ServiceModel::getData);
Observable obsCombined =
Observable.zip(
categoriesMapObservable
.subscribeOn(Schedulers.io()),
serviceListObservable
.subscribeOn(Schedulers.io()),
Pair::new
)
.flatMap(hashMapListPair -> {
HashMap<Integer, CategoryData> categoriesMap = hashMapListPair.first;
return Observable.from(hashMapListPair.second)
.filter(serviceData -> categoriesMap.containsKey(serviceData.getCategoryTypeId()))
.toList();
}, (hashMapListPair, serviceDataList) -> new Pair<>(hashMapListPair.first.values(), serviceDataList));
the output result depends on you , here I apply at the end a selector of flatMap() that will create a Pair of Collection of CategoryData and a filtered list of ServiceData, you can of course create whatever custom Object you need for that.
I'm not sure you're gaining much from this, it's seems more efficient from complexity perspective, assuming HashMap is O(1), where categories are N, and services are M, you have here N + M (N constructing the map, M iterating the list and querying the map), while your naive implementation will be N x M.
as for code complexity, i'm not sure it worth it, you can apply your logic at the end of the zip for filtering, or use some library that might be doing filter more efficiently.
P.S the observerOn(AndroidSchedulers.mainThread() is unnecessary so I removed it.

sort json response on click and display accordingly in titanium

Hi I have json response which looks like this.
{
"id": "7",
"issue_title": "Apr - May 2015",
"issue_no": "Issue 1.4",
"cover_image_url": "http://www.link.org/apr--may-2015-7.jpg",
"synopsis_pdf_url": "",
"advertisers_pdf_url": "",
"issue_date": "01-04-2015",
"issue_year": "2015"
},
{
"id": "3",
"issue_title": "Feb-Mar 2015",
"issue_no": "Issue 1.3",
"cover_image_url": "http://www.link.org/febmar-2015-3.jpg",
"synopsis_pdf_url": "http://www.link.org/febmar-2015-3.pdf",
"advertisers_pdf_url": "http://www.link.org/febmar-2015-3.pdf",
"issue_date": "01-02-2015",
"issue_year": "2015"
},
{
"id": "2",
"issue_title": "Dec 2014 - Jan 2015",
"issue_no": "Issue 1.2",
"cover_image_url": "http://www.link.org/dec-2014--jan-2015-2.jpg",
"synopsis_pdf_url": "",
"advertisers_pdf_url": "",
"issue_date": "01-12-2014",
"issue_year": "2014"
},
{
"id": "1",
"issue_title": "Oct - Nov 2014",
"issue_no": "Issue 1.1",
"cover_image_url": "http://www.link.org/oct--nov-2014-1.jpg",
"synopsis_pdf_url": "",
"advertisers_pdf_url": "",
"issue_date": "01-10-2014",
"issue_year": "2014"
}
Then I retrieved "issue_year" of each element and displayed in picker with multiple occurrence deleted.
Basically when the window loads all the elements are displayed but after that on a click of picker element (i.e 2014 ,2015 ) the elements should get display.
Tableview is used for displaying elements so on each click the array passed to tableview should get change according to year selected from picker.
var i,
len = singleData.length,
sorted = [],
obj = {};
for ( i = 0; i < len; i++) {
obj[singleData[i]] = 0;
}
for (i in obj) {
sorted.push(i);
}
for (var i = 0; i < sorted.length; i++) {
data[i] = Ti.UI.createPickerRow({
title : sorted[i]
});
}
$.picker.add(data);
$.picker.addEventListener('change',function(e){
//what will be the code here
});
Can anyone help on this?
This is fairly simple. here's what you need to do:
Add a custom property to your picker, containing the obj to be sent:
for (var i = 0; i < sorted.length; i++) {
data[i] = Ti.UI.createPickerRow({
title : sorted[i],
obj: MY_OBJ // HERE YOU NEED TO PASS THE OBJECT THAT WILL BE SENT TO DISPLAY
});
}
Next, in your listener, you can access that object using:
$.picker.addEventListener('change',function(e){
alert(e.source.obj); // This will alert the correct object you created in the picker!
});
Hope it helps!
-Lucas

How to create views dynamically from json in android listview? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I want to create radio button,checkbox,spinner dynamically from web service. Below is my response.
{
"getSurvey": {
"ErrorCode": "0",
"Result": "Success",
"Response": [
{
"SurveyId": "91",
"SurveyName": "Sample Survey",
"Questions": [
{
"QuestionId": "553",
"QuestionText": "<p style=\"margin: 0px; text-align: left;\">Are you satisfied with Cement Quality?</p>",
"Type": "RadioButtonList",
"Mandatory": "Y",
"OptionValue": [
{
"AnswerId": "2220",
"AnswerValue": "Excellent"
},
{
"AnswerId": "2221",
"AnswerValue": "Good"
},
{
"AnswerId": "2222",
"AnswerValue": "Satisfactory"
},
{
"AnswerId": "2223",
"AnswerValue": "Poor"
}
]
},
{
"QuestionId": "554",
"QuestionText": "How will you rate Cement? (0= Lowest and 7= Highest) ",
"Type": "DropDownList",
"Mandatory": "Y",
"OptionValue": [
{
"AnswerId": "2224",
"AnswerValue": "0"
},
{
"AnswerId": "2225",
"AnswerValue": "1"
},
{
"AnswerId": "2226",
"AnswerValue": "2"
},
{
"AnswerId": "2227",
"AnswerValue": "3"
},
{
"AnswerId": "2228",
"AnswerValue": "4"
},
{
"AnswerId": "2229",
"AnswerValue": "5"
},
{
"AnswerId": "2230",
"AnswerValue": "6"
},
{
"AnswerId": "2231",
"AnswerValue": "7"
}
]
},
{
"QuestionId": "555",
"QuestionText": "What Kind of issues you face while Delivery?",
"Type": "ListBox",
"Mandatory": "Y",
"OptionValue": [
{
"AnswerId": "2232",
"AnswerValue": "Logistic Issue"
},
{
"AnswerId": "2233",
"AnswerValue": "Material Handeling "
},
{
"AnswerId": "2234",
"AnswerValue": "Stock not available"
},
{
"AnswerId": "2235",
"AnswerValue": "Wastage of Cement"
},
{
"AnswerId": "2236",
"AnswerValue": "Others"
}
]
},
{
"QuestionId": "559",
"QuestionText": "Do you like Cement?",
"Type": "CheckBoxList",
"Mandatory": "Y",
"OptionValue": [
{
"AnswerId": "2237",
"AnswerValue": "Yes"
},
{
"AnswerId": "2238",
"AnswerValue": "No"
}
]
}
]
}
]
}
}
Based on type i need to create views dynamically. Please someone give me the idea or solution how to achieve this. After created views dynamically i need to get all the selected values from created views.
Thanks.
you can use json2view library to create dynamically view.
https://github.com/Avocarrot/json2view
This is tricky, you need to learn how to create layouts dynamically in code first. I would start off my reviewing tutorials found here: http://www.dreamincode.net/forums/topic/130521-android-part-iii-dynamic-layouts/
You would need to create a class that could parse this data and create the views specifically for your values. Once that is done, you could read the data again or have it stored so you could load the data to the screen. This could also be done at the same time you are creating the layout.
If the type of Questions like '"Type": "RadioButtonList"' are known in advance, you can create predefined layouts addressing each of those types. You then need to parse and look for the object /Response/Questions/Type in your json and inflate the appropriate layout. You also need to create an adapter that can accept list of options for each type. Plugin the adapter and the view behind the layout.
I do something similar for the product I work on. After I retrieve the json feed, I would scan through the Questions to see the type of layouts I require. In my scenario, I create a ViewPager dynamically: each entry into the view pager would have a layout corresponding to the Type of Question. I would then build up the list of options for each Question Type and feed them to an adapter that is bound to listview or drop down list or a custom type that resides in the layout file.
just parse and set data to static data in code
ScrollView sv = new ScrollView(this);
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
sv.addView(ll);
//radio list
RadioGroup group = new RadioGroup(this);
group.setOrientation(RadioGroup.VERTICAL);
RadioButton btn1 = new RadioButton(this);
btn1.setText("BTN1");
group.addView(btn1);
RadioButton btn2 = new RadioButton(this);
btn2.setText("BTN2");
group.addView(btn2);
ll.addView(group);
//drop down
Spinner spiner = new Spinner(this);
List<String> data = new ArrayList<String>();
data.add("Spinner - one");
data.add("Spinner - two");
data.add("Spinner - three");
data.add("Spinner - four");
data.add("Spinner - five");
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, data);
spiner.setAdapter(adapter);
ll.addView(spiner);
//listview
ListView listData = new ListView(this);
List<String> dataList = new ArrayList<String>();
dataList.add("List - one");
dataList.add("List - two");
dataList.add("List - three");
dataList.add("List - four");
dataList.add("List - five");
dataList.add("List - six");
dataList.add("List - seven");
dataList.add("List - eight");
dataList.add("List - nine");
dataList.add("List - ten");
dataList.add("List - eleven");
dataList.add("List - twelve");
dataList.add("List - thirteen");
dataList.add("List - fourteen");
dataList.add("List - fifteen");
ArrayAdapter<String> listAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, dataList);
listData.setAdapter(listAdapter);
ll.addView(listData);
this.setContentView(sv);
setListViewHeightBasedOnChildren(listData);
support method
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
listView.requestLayout();
}
Try this. Hope it might help you.
public class MainActivity extends Activity {
String response = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
JSONObject jObject1 = new JSONObject(response);
JSONObject jObject2 = jObject1.getJSONObject("getSurvey");
if (jObject2.getString("ErrorCode").equals("0")) {
JSONArray jArray = jObject2.getJSONArray("Response");
JSONObject jObject3 = jArray.getJSONObject(0);// Response array
// contains only
// one object ,
// otherwise we
// can put loop
JSONArray jArray2 = jObject3.getJSONArray("Questions");
for (int i = 0; i < jArray2.length(); i++) {
JSONObject jObjectQ = jArray2.getJSONObject(i);
String QUESTION = jObjectQ.getString("QuestionText"); // Similarly
// you
// can
// take
// other
// parameters.
JSONArray jArrayA = jObjectQ.getJSONArray("OptionValue");
for (int j = 0; j < jArrayA.length(); j++) {
JSONObject jObjectOPTION = jArrayA.getJSONObject(j);
String ANSWERID = jObjectOPTION.getString("AnswerId");
String ANSWERVALUE = jObjectOPTION
.getString("AnswerValue");
// Add Dynamically in Spinner or create Radiobutton as
// per your requirement
}
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
You can also set Id dynamically of each controls. based on that you should call any method and check id of the controls.

JSON exctract key for fill Spinner

I would like to extract into two separate array the key "desc" and "type" in my JSON file.
I get the file from an ftp site and I don't know how many entry there are.
After I have the String Array, I would like to fill a Spinner by the "desc" value.
How can do that?
this is my JSON file
{
"Pagnerine":[{
"Cialda":[{
"userId":1,
"desc":"Sottozero/Estate",
"type":"ct"
},
{
"userId":2,
"desc":"Piccolo/Primavera",
"type":"ct"
},
{
"userId":3,
"desc":"Medio",
"type":"ct"
},
{
"userId":4,
"desc":"Grande",
"type":"ct"
}
],
"Cartone":[{
"userId":1,
"desc":"16B",
"type":"ct"
},
{
"userId":2,
"desc":"17",
"type":"ct"
},
{
"userId":3,
"desc":"34",
"type":"ct"
},
{
"userId":4,
"desc":"20",
"type":"ct"
}
]
}
],
"Cucchiaini":[],
"Vaschette":[],
"Zuccheri":[],
"versione":"100"
}
i have tried to implement this code for obtain how many entry (desc or type) there are, but fail because count only the first part "Cialda" and "Cartone"
Iterator<String> iter = jObj.keys();
while (iter.hasNext()) {
String key = iter.next();
try {
JSONArray jArray = jObj.getJSONArray(key);
// looping through
entry += jArray.length();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I would suggest implementing an easier to maintain solution for this so you can get it into easy to use POJOs and adapt to potential changes later on. My preferred approach is to use [GSON}(https://code.google.com/p/google-gson/), but there's also Jackson.
Take a look at the GSON User Guide for specifics, but basically here's the concept.
Let's say that my JSON is the following:
JSON
{ "items" :
[
{
"type" : "food",
"name" : "Tacos"
},
{
"type" : "food",
"name" : "Bacon"
},
{
"type" : "food",
"name" : "Beer"
},
]
}
I would create the following objects:
Items.java
public class Items {
List<Item> items;
}
Item.java
public class Item {
String type;
String name;
}
Then I would simply do the following to create my Items object once I got the JSON.
Items deliciousFoodStuffs = gson.fromJson(json, Items.class);
This would result in me having deserialized my JSON into POJOs which I can use to my hearts content.
Let's say that I don't want to map via the field names but instead map to Java fields named differently, I would do the following instead:
Item.java
public class Item {
#SerializedName("type")
String typeValue;
#SerializedName("name")
String nameValue;
}
Using the same call as before
Items deliciousFoodStuffs = gson.fromJson(json, Items.class);
I will receive the same result with this, expect my variables are named differently.
Note: Beer, Bacon, and Tacos are all delicious and not necessarily organized in the order of deliciousness.
The code you've posted doesn't match your objective in the question. But to answer the issue of why entry only counts the first two elements (and assuming jObj is a valid JSONObject containing the Pagnerine element) Try this:
for(int i = 0; i < jObj.length(); i++) {
JSONObject childObject = new JSONObject(jObj.get(i).toString());
entry += childObject.length();
}
entry should now contain the total number of elements there are in your JSON file. The change is to iterate through each of the parent elements (in this case Cialda and Cartone), and for each of these elements count the number of child elements.
Edit
As per your comment, this can be amended easily to get a count of the parents, and children:
for(int i = 0; i < jObj.length(); i++) {
parentCount += jObj.length();
JSONObject childObject = new JSONObject(jObj.get(i).toString());
childCount += childObject.length();
}

Categories

Resources