I retrieve a quiz from a webservice and i want to render it like this,
I'm trying to use RadioButtons programmatically generated.
I have image and text quiz, I use rg.setOrientation(); to display quiz horizontaly / verticaly depends on the quizz type.
I tried to add image using Drawable but I can not put the RadioButton centered under the image. I'm only able to get this.
I can not center the text either
There is the code I wrote.
final RadioGroup rg = (RadioGroup) v.findViewById(R.id.radio_group);
final int[] try_answer = {NUMBER_OF_TRY_MAX};
if (question.getImage()) {
if (!isTablet) {
rg.setOrientation(LinearLayout.VERTICAL);
} else {
rg.setOrientation(LinearLayout.HORIZONTAL);
}
rg.setGravity(Gravity.CENTER_HORIZONTAL);
for (int i = 0; i < answers.size(); i++) {
Answer answer = answers.get(i);
RadioButton button = new RadioButton(getContext());
db.open();
Image img = db.getImageWithURL(answer.getPicture());
db.close();
String localName = img.getImage();
String file = path + localName;
Bitmap bitmap = BitmapFactory.decodeFile(file);
Drawable d = new BitmapDrawable(getContext().getResources(), Bitmap.createScaledBitmap(bitmap, 300, 300, true));
d.setBounds(0, 0, 300, 300);
button.setCompoundDrawablesWithIntrinsicBounds(null,d,null,null);
button.setTextColor(Color.WHITE);
button.setTag(answer.right_answer);
button.setGravity(Gravity.LEFT);
button.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
button.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
int[][] states = new int[][]{
new int[]{ android.R.attr.state_enabled}, // enabled
new int[]{-android.R.attr.state_enabled}, // disabled
new int[]{-android.R.attr.state_checked}, // unchecked
new int[]{ android.R.attr.state_checked}, // checked
new int[]{ android.R.attr.state_pressed} // pressed
};
int[] colors = new int[]{
Color.WHITE,
Color.GRAY,
Color.WHITE,
Color.BLUE,
Color.BLUE
};
ColorStateList myList = new ColorStateList(states, colors);
button.setButtonTintList(myList);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (try_answer[0] > 0) {
if ((Boolean) v.getTag()) {
displayRightAnswerImage(rg);
question.setAnswered(true);
checkIfAllQuestionsAnswered();
} else {
try_answer[0]--;
if (try_answer[0] == 0) {
displayRightAnswerImage(rg);
question.setAnswered(true);
checkIfAllQuestionsAnswered();
} else {
int selected = rg.getCheckedRadioButtonId();
RadioButton rb = (RadioButton) v.findViewById(selected);
Drawable[] drawables = rb.getCompoundDrawables();
Drawable draw = drawables[1];
draw.setAlpha(125);
Toast.makeText(getContext(), "il reste " + try_answer[0] + " essais", Toast.LENGTH_SHORT).show();
}
}
}
}
});
rg.addView(button);
}
} else {
rg.setOrientation(LinearLayout.VERTICAL);
for (int i = 0; i < answers.size(); i++) {
Answer answer = answers.get(i);
final RadioButton button = new RadioButton(getContext());
rg.addView(button);
button.setText(answer.getTitle());
button.setTextColor(Color.WHITE);
button.setTag(answer.right_answer);
button.setGravity(Gravity.CENTER_HORIZONTAL);
button.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (try_answer[0] > 0) {
if ((Boolean) v.getTag()) {
displayRightAnswer(rg);
question.setAnswered(true);
checkIfAllQuestionsAnswered();
} else {
try_answer[0]--;
if (try_answer[0] == 0) {
displayRightAnswer(rg);
question.setAnswered(true);
checkIfAllQuestionsAnswered();
} else {
Toast.makeText(getContext(), "il reste " + try_answer[0] + " essais", Toast.LENGTH_SHORT).show();
}
}
}
}
});
}
}
return v;
How can I get to make the display look similar to the first screen.
Is it possible or should I use another component than radiobutton to render it properly ?
Use Relativelayout.LayoutParams object and add rules to it. Check this
As you can see below, I am dynamically creating some sort of quiz with different types of questions (RadioButtons and CheckBoxes).
So I can generate them correctly and they appear as they should.
At the end of the questions there is a normal Button.
And I want to make it available for click only after all the questions have been answered.
I have a function to make sure that all the RadioButtons are answered.
But since I have two types of buttons I can't figure out how to make sure that the questions with the CheckBox answers have at least 1 checked answer.
I have the following code:
ArrayList<RadioGroup> arrGroup;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_quiz);
buttHole = (Button) findViewById(R.id.button1);
buttHole.setEnabled(false);
getQuestions();
//Creating the list of Questions
LinearLayout mLinearLayout = (LinearLayout) findViewById(R.id.linear1);
arrGroup = new ArrayList<RadioGroup>();
try
{
for (int i = 0; i <= question.length; i++)
{
if(question[i].multichoice == true)
{
TextView title2 = new TextView(this);
title2.setText(question[i].questionName);
title2.setTextColor(Color.BLACK);
mLinearLayout.addView(title2);
for(int zed = 0; zed < question[i].answers.length; zed++)
{
CheckBox box = new CheckBox(this);
box.setText(question[i].answers[zed].answer);
box.setId(zed);
mLinearLayout.addView(box);
}
}
else
{
// create text button
TextView title = new TextView(this);
title.setText(question[i].questionName);
title.setTextColor(Color.BLACK);
mLinearLayout.addView(title);
// create radio button
final RadioButton[] rb = new RadioButton[question[i].answers.length];
RadioGroup radGr = new RadioGroup(this);
// take a reference of RadioGroup view
arrGroup.add(radGr);
radGr.setOrientation(RadioGroup.VERTICAL);
radGr.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
checkQuestionsAnswer();
}
});
for (int j = 0; j < question[i].answers.length; j++) {
rb[j] = new RadioButton(this);
radGr.addView(rb[j]);
rb[j].setText(question[i].answers[j].answer);
}
mLinearLayout.addView(radGr);
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
public boolean checkQuestionsAnswer()
{
int count = arrGroup.size();
for (int i = 0; i < count; i++)
{
if (arrGroup.get(i).getCheckedRadioButtonId() == -1)
{
Toast.makeText(getApplicationContext(), "Not all questions are answered!", Toast.LENGTH_SHORT).show();
return false;
}
}
Toast.makeText(getApplicationContext(), "Thank you!", Toast.LENGTH_SHORT).show();
buttHole.setEnabled(true);
//Return true if all answer are given
return true;
}
If you have less than 10 answers per question set the id of the checkboxes to (i*10)+zed for example. This way you could loop through the answers like this
for(int i=0; i<question.length; i++){
boolean questionAnswered = false;
for(int zed = 0; zed < question[i].answers.length; zed++) {
CheckBox box = (CheckBox) findViewById(i*10+zed);
if(box != null && box.isChecked()) {
questionAnswered = true;
...
}
}
}
I didn't try this code, and it's just a quick and dirty hint, but I hope it helps.
I have 3 row in table, where every row has 3 checkbox. I want to check appropriate CheckBox according to its id.
I have to check following ids CheckBox.
tempArray =[1-2-3,3-2,null];
i am already splitting these data and putting in string array(setopts).more see my code.
Null for no check any CheckBox with this row.
I am doing this code in my project.
Vector<CheckBox> chkBoxList = new Vector<CheckBox>();
Vector<TextView> txtViewList = new Vector<TextView>();
// mat_elemItemSetChk.get(0).size() OF VALUE IS 3
for (int n = 0; n < mat_elemItemSetChk.get(0).size(); n++) {
LinearLayout llayout = new LinearLayout(getContext());
ll.setOrientation(android.widget.LinearLayout.VERTICAL);
cb = new CheckBox(getContext());
tv = new TextView(getContext());
for (int r = 0; r < tempArray.size() ; r++) {
isContains=tempArray.get(r).contains(individualValueSeparator);
if(isContains){
setOpts = tempArray.get(r).split("\\-");
for (int k = 0; k < setOpts.length; k++)
{
ItemValue iv = (ItemValue) mat_elemItemSetChk.get(0).get(n);
if (((int) iv.getId()) == Integer.parseInt(setOpts[k]))
{
mat_elemItemSetChk.get(n).get(Integer.parseInt(setOpts[k])-1);
cb.setChecked(true);
}
}
}else{
if(tempArray.get(r).toString().equalsIgnoreCase("null")||tempArray.get(r).toString()!=null){
String temp;
String px[]= null;
temp = tempArray.get(r).toString();
ItemValue iv = (ItemValue) mat_elemItemSetChk.get(0).get(n);
if (((int) IV.getId()) == Integer.parseInt(temp))
{
mat_elemItemSetChk.get(0).get(Integer.parseInt(temp) - 1);
cb.setChecked(true);
}
}else{
cb.setChecked(false);
}
}
}
tv.setText(mat_elemItemSetChk.get(0).get(n) .toString());
llayout.addView(cb);
llayout.addView(tv);
chkBoxList.add(cb);
txtViewList.add(tv);
ll.addView(llayout);
// this.addView(tableLayout);
}
Thank you in advance.
make an array selchkboxlist and store the selected checkbox id in it and check condition like selchkboxlist.isEmpty() if true then then show error msg other wise go ahed...
selchkboxlist=new ArrayList<String>();
cbs = new CheckBox[8];
// generate dynamic item check box code
for(int k = 0; k<8; k++)
{
cbs[k] = new CheckBox(getApplicationContext());
#SuppressWarnings("deprecation")
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
rl.addView(cbs[k], params);
int j =k+1;
cbs[k].setText("ITEM" + j);
cbs[k].setTextColor(Color.parseColor("#000000"));
cbs[k].setId(k+1);
cbs[k].setPadding(70, 20, 10, 10);
// check box on click listener for add in to produduct array with quntity
cbs[k].setOnClickListener( new View.OnClickListener()
{
public void onClick(View v)
{
String chk = null;
if (((CheckBox) v).isChecked()) {
chk = Integer.toString(v.getId());
selchkboxlist.add(chk);
} else {
selchkboxlist.remove(chk);
}
}
});
}
// button on click listener code
b.setOnClickListener(new OnClickListener() {
#SuppressLint("SdCardPath")
public void onClick(View v) {
if (! selchkboxlist.isEmpty()) {
shoe erroe msg here
}else{
go ahed
}
}
});
I have many buttons(81) from the left and right part of my layout. All in all, I have 162 buttons. I put those buttons to Button[] and I handle it properly.
private int[] right_lung = { R.id.btn_right_106, R.id.btn_right_113,
R.id.btn_right_114, R.id.btn_right_115, R.id.btn_right_116, R.id.btn_right_121,
R.id.btn_right_122, R.id.btn_right_123, R.id.btn_right_124, R.id.btn_right_125,
R.id.btn_right_129, R.id.btn_right_130, R.id.btn_right_131, R.id.btn_right_132,
R.id.btn_right_133, R.id.btn_right_134, R.id.btn_right_137, R.id.btn_right_138,
R.id.btn_right_139, R.id.btn_right_140, R.id.btn_right_141, R.id.btn_right_142,
R.id.btn_right_143, R.id.btn_right_145, R.id.btn_right_146, R.id.btn_right_147,
R.id.btn_right_148, R.id.btn_right_149, R.id.btn_right_150, R.id.btn_right_151,
R.id.btn_right_152, R.id.btn_right_153, R.id.btn_right_154, R.id.btn_right_155,
R.id.btn_right_156, R.id.btn_right_157, R.id.btn_right_158, R.id.btn_right_159,
R.id.btn_right_160, R.id.btn_right_161, R.id.btn_right_162, R.id.btn_right_163,
R.id.btn_right_164, R.id.btn_right_165, R.id.btn_right_166, R.id.btn_right_167,
R.id.btn_right_168, R.id.btn_right_169, R.id.btn_right_170, R.id.btn_right_171,
R.id.btn_right_172, R.id.btn_right_173, R.id.btn_right_174, R.id.btn_right_175,
R.id.btn_right_176, R.id.btn_right_177, R.id.btn_right_178, R.id.btn_right_179,
R.id.btn_right_180, R.id.btn_right_181, R.id.btn_right_182, R.id.btn_right_183,
R.id.btn_right_184, R.id.btn_right_185, R.id.btn_right_186, R.id.btn_right_187,
R.id.btn_right_188, R.id.btn_right_189, R.id.btn_right_190, R.id.btn_right_191,
R.id.btn_right_192, R.id.btn_right_194, R.id.btn_right_195, R.id.btn_right_196,
R.id.btn_right_197, R.id.btn_right_198, R.id.btn_right_199, R.id.btn_right_200,
R.id.btn_right_205, R.id.btn_right_206, R.id.btn_right_207 };
private Button[] btn_right = new Button[right_lung.length];
private int[] left_lung = { R.id.btn_left_7, R.id.btn_left_13, R.id.btn_left_14,
R.id.btn_left_15, R.id.btn_left_16, R.id.btn_left_20, R.id.btn_left_21,
R.id.btn_left_22, R.id.btn_left_23, R.id.btn_left_24, R.id.btn_left_27,
R.id.btn_left_28, R.id.btn_left_29, R.id.btn_left_30, R.id.btn_left_31,
R.id.btn_left_32, R.id.btn_left_34, R.id.btn_left_35, R.id.btn_left_36,
R.id.btn_left_37, R.id.btn_left_38, R.id.btn_left_39, R.id.btn_left_40,
R.id.btn_left_41, R.id.btn_left_42, R.id.btn_left_43, R.id.btn_left_44,
R.id.btn_left_45, R.id.btn_left_46, R.id.btn_left_47, R.id.btn_left_48,
R.id.btn_left_49, R.id.btn_left_50, R.id.btn_left_51, R.id.btn_left_52,
R.id.btn_left_53, R.id.btn_left_54, R.id.btn_left_55, R.id.btn_left_56,
R.id.btn_left_57, R.id.btn_left_58, R.id.btn_left_59, R.id.btn_left_60,
R.id.btn_left_61, R.id.btn_left_62, R.id.btn_left_63, R.id.btn_left_64,
R.id.btn_left_65, R.id.btn_left_66, R.id.btn_left_67, R.id.btn_left_68,
R.id.btn_left_69, R.id.btn_left_70, R.id.btn_left_71, R.id.btn_left_72,
R.id.btn_left_73, R.id.btn_left_74, R.id.btn_left_75, R.id.btn_left_76,
R.id.btn_left_77, R.id.btn_left_78, R.id.btn_left_79, R.id.btn_left_80,
R.id.btn_left_81, R.id.btn_left_82, R.id.btn_left_83, R.id.btn_left_84,
R.id.btn_left_85, R.id.btn_left_86, R.id.btn_left_87, R.id.btn_left_88,
R.id.btn_left_89, R.id.btn_left_90, R.id.btn_left_91, R.id.btn_left_92,
R.id.btn_left_93, R.id.btn_left_94, R.id.btn_left_95, R.id.btn_left_98,
R.id.btn_left_99, R.id.btn_left_100, };
private Button[] btn_left = new Button[left_lung.length];
Whenever I click on the button, just like in mine sweeper game, many buttons are randomly opened. And when it is opened, I am changing its background into R.drawable.affected. The goal of the game is to open all the buttons in left and right. My question is this, how can I check if all of the buttons are set in R.drawable.affected? Because after that, I will execute a method that will congratulate the user. Thanks in advance.
EDIT:
for (int i = 0; i < btn_right.length; i++) {
final int a = i;
int counter_total_affected = 0;
btn_right[i].setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (counter == 1) {
right_lung.add(a);
btn_right[a].setBackgroundResource(R.drawable.affected);
counter_total_affected++;
} else if (counter == 2) {
for (int i = 0; i < 2; i++) {
int n = i;
right_lung.add(a + n);
}
try {
for (int i = 0; i < 2; i++) {
int n = i;
btn_right[a + n].setBackgroundResource(R.drawable.affected);
counter_total_affected++;
}
} catch (Exception e) {
e.printStackTrace();
}
} else if (counter == 3) {
right_lung.add(a);
btn_right[a].setBackgroundResource(R.drawable.affected);
counter_total_affected++;
} else if (counter == 4) {
for (int i = 0; i < 25; i++) {
int n = i;
right_lung.add(a + n);
}
try {
for (int i = 0; i < 25; i++) {
int n = i;
btn_right[a + n].setBackgroundResource(R.drawable.affected);
counter_total_affected++;
}
} catch (Exception e) {
e.printStackTrace();
}
} else if (counter == ...) {
//statements...
} else if (counter_total_affected == (btn_left.length + btn_right.length)) {
//CONGRATULATORY METHOD
}
counter++;
}
}
Increment the counter each time you change background of button and compare its value with length of button array. if both are same that means, all button backgrounds are set.
Try this :
for (int i = 0; i < btn_right.length; i++) {
final int b = i;
btn_right[i].setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if btn_right[i].getDrawable().getConstantState().equals
(getResources().getDrawable(R.drawable.affected).getConstantState()))
{
if(counter == btn_right.length){
//Congratulate user...
}
}else{
btn_right[b].setBackgroundResource(R.drawable.affected);
counter++;
}
}
}
U can set Tag:
for (int i = 0; i < btn_right.length; i++) {
final int b = i;
btn_right[i].setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (counter == 1) {
right_affected.add(b);
btn_right[b].setBackgroundResource(R.drawable.affected);
btn_right[b].setTag('1');
} else {
//some stuff here...
}
}
}
after congratulate the user set its Tag to 0.
EDIT:
ArrayList<Integer> arrayofId =new ArrayList<Integer>();
#Override
public void onClick(View v) {
if (counter == 1) {
right_affected.add(b);
btn_right[b].setBackgroundResource(R.drawable.affected);
arrayofId.add(b);//need to convert int to Integer.
} else {
//some stuff here...
}
}
To congratulate:
for(int i=0;i<arrayofId.size();i++)
{
// you can get here id of effected buttons
}
I have table layout in which I am adding textviews dynamically.
I m setting OnTouch listener on text view. On MotionEvent.ACTION_DOWN I show popup and on MotionEvent.ACTION_UP. I am removing that popup but I want if touch is removed from the textview then also the pop should remove I have tried with MotionEvent.ACTION_MOVE ,MotionEvent.ACTION_OUTSIDE but both are not working
public void addButton_with_filter(final Test test,
TableRow.LayoutParams rowParams, Activity context) {
ArrayList<Integer> filteredquestionno;
TableLayout tl = new TableLayout(context);
tl.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT));
LinearLayout filterlayout = (LinearLayout) findViewById(R.id.filterlayout);
filterlayout.removeAllViewsInLayout();
filterlayout.setBackgroundResource(R.drawable.background1);
int j = 0;
int k = 0;
filteredquestionno = getLayoutFilteredQuestionNumber(test
.getQuestions());
int size = filteredquestionno.size();
if (size == 0) {
Toast.makeText(this,
"NO QUSTION IS AVAILABLE OF THIS FILTER TYPE !",
Toast.LENGTH_LONG).show();
}
int norows = (size / 10) + 1;
{
for (int i = 0; i < norows; i++) {
TableRow currentRow = new TableRow(FilterActivity.this);
// currentRow.setBackgroundResource(R.drawable.background1);
while (j < 10 && k < size) {
j++;
final TextView qindex = new TextView(FilterActivity.this);
qindex.setGravity(Gravity.CENTER);
int index = filteredquestionno.get(k);
Question question = test.getQuestionAtIndex(index);
if (question != null) {
if (submited == true) {
if (question.isSkipped()) {
qindex.setBackgroundResource(R.drawable.skipped_answer);
} else if (question.isCorrectlyAnswered()) {
qindex.setBackgroundResource(R.drawable.correct_answer);
} else if (question.isAttempted()) {
qindex.setBackgroundResource(R.drawable.wrong_answer);
} else {
qindex.setBackgroundResource(R.drawable.unattempted_question);
}
} else if (submited == false) {
if (question.isSkipped()) {
qindex.setBackgroundResource(R.drawable.skipped_answer);
} else if (question.isAttempted()) {
qindex.setBackgroundResource(R.drawable.attempted_question);
} else {
qindex.setBackgroundResource(R.drawable.unattempted_question);
}
enter code here }
} else {
qindex.setBackgroundResource(R.drawable.unattempted_question);
}
qindex.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
qindex.setTextSize(11);
if ((index + 1) < 10) {
qindex.setText("0" + (index + 1));
} else {
qindex.setText("" + (index + 1));
}
k++;
qindex.setId(k);
qindex.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent event) {
String text = (String) qindex.getText();
String t = text.trim();
int questionindex = Integer.parseInt(t);
LayoutInflater questionbutton_inflater = (LayoutInflater) getBaseContext()
.getSystemService(LAYOUT_INFLATER_SERVICE);
View questionbutton_view = questionbutton_inflater
.inflate(R.layout.filterbutton, null);
final PopupWindow questiontext_popupwindow = new PopupWindow(
questionbutton_view,
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
questiontext_popupwindow
.setContentView(questionbutton_view);
TextView tv = (TextView) questionbutton_view
.findViewById(R.id.texttoadd);
tv.setText(text);
if (event.getAction() == MotionEvent.ACTION_DOWN) {
questiontext_popupwindow.showAsDropDown(qindex,
0, -125);
}
if (event.getAction() == MotionEvent.ACTION_UP) {
questiontext_popupwindow.dismiss();
test.setLastQuestionAttempted(questionindex - 1);
FilterActivity.this.finish();
}
if (event.getAction() == MotionEvent.ACTION_MOVE) {
questiontext_popupwindow.dismiss();
}
return true;
}
});
currentRow.addView(qindex, rowParams);
}
j = 0;
tl.addView(currentRow);
}
filterlayout.addView(tl);
}
Typical mistake - you create pop-up every time MotionEvent fires. So the previously created pop-up cannot be dismissed, because you lost the link to it - another time your program enters onTouch() you will not have the link to your pop-up (because it is declared in onTouch()). Make your pop-up a field of OnTouchListener. And create it ONLY ONCE.
Step-by-step:
MotionEvent.ACTION_DOWN fires - you create and show pop-up, it is on screen
MotionEvent.ACTION_UP fires - you create new pop-up and dismissing it, but not the old one