├── .DS_Store ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── codeql-analysis.yml ├── .gitignore ├── .idea ├── codeStyles │ └── Project.xml ├── modules.xml └── vcs.xml ├── CheckboxQuestion ├── .gitignore ├── .idea │ ├── .name │ ├── codeStyles │ │ └── Project.xml │ ├── gradle.xml │ ├── jarRepositories.xml │ ├── misc.xml │ ├── runConfigurations.xml │ └── vcs.xml ├── CheckboxQuestion │ ├── .gitignore │ ├── build.gradle │ ├── consumer-rules.pro │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── aadyad │ │ │ └── checkboxquestion │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── aadyad │ │ │ │ └── checkboxquestion │ │ │ │ ├── OnAnswerChangedListener.java │ │ │ │ ├── Question.java │ │ │ │ ├── QuestionList.java │ │ │ │ ├── QuestionListSettings.java │ │ │ │ └── Views │ │ │ │ ├── MultipleAnswerQuestion.java │ │ │ │ ├── MultipleChoiceQuestion.java │ │ │ │ └── YesOrNoQuestion.java │ │ └── res │ │ │ ├── layout │ │ │ ├── multiple_answer_question.xml │ │ │ ├── multiple_choice_question.xml │ │ │ └── yes_or_no_question.xml │ │ │ └── values │ │ │ └── attrs.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── aadyad │ │ └── checkboxquestion │ │ └── ExampleUnitTest.java ├── app │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── aadyad │ │ │ └── checkboxquestions_library │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── aadyad │ │ │ │ └── checkboxquestions_library │ │ │ │ └── MainActivity.java │ │ └── res │ │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── drawable │ │ │ └── ic_launcher_background.xml │ │ │ ├── layout │ │ │ └── activity_main.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── aadyad │ │ └── checkboxquestions_library │ │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── LICENSE └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EunoiaC/Checkbox-Questions/c4accf0037ab27b4af84abf9b26b7177b31f1011/.DS_Store -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ main ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main ] 20 | schedule: 21 | - cron: '15 18 * * 0' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'java' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 37 | # Learn more: 38 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 39 | 40 | steps: 41 | - name: Checkout repository 42 | uses: actions/checkout@v2 43 | 44 | # Initializes the CodeQL tools for scanning. 45 | - name: Initialize CodeQL 46 | uses: github/codeql-action/init@v1 47 | with: 48 | languages: ${{ matrix.language }} 49 | # If you wish to specify custom queries, you can do so here or in a config file. 50 | # By default, queries listed here will override any specified in a config file. 51 | # Prefix the list here with "+" to use these queries and those in the config file. 52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 53 | 54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 55 | # If this step fails, then you should remove it and run the build manually (see below) 56 | - name: Autobuild 57 | uses: github/codeql-action/autobuild@v1 58 | 59 | # ℹ️ Command-line programs to run using the OS shell. 60 | # 📚 https://git.io/JvXDl 61 | 62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 63 | # and modify them (or add more) to build your code if your project 64 | # uses a compiled language 65 | 66 | #- run: | 67 | # make bootstrap 68 | # make release 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@v1 72 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | *.aab 5 | 6 | # Files for the ART/Dalvik VM 7 | *.dex 8 | 9 | # Java class files 10 | *.class 11 | 12 | # Generated files 13 | bin/ 14 | gen/ 15 | out/ 16 | 17 | # Gradle files 18 | .gradle/ 19 | build/ 20 | 21 | # Local configuration file (sdk path, etc) 22 | local.properties 23 | 24 | # Proguard folder generated by Eclipse 25 | proguard/ 26 | 27 | # Log Files 28 | *.log 29 | 30 | # Android Studio Navigation editor temp files 31 | .navigation/ 32 | 33 | # Android Studio captures folder 34 | captures/ 35 | 36 | # IntelliJ 37 | *.iml 38 | .idea/workspace.xml 39 | .idea/tasks.xml 40 | .idea/gradle.xml 41 | .idea/assetWizardSettings.xml 42 | .idea/dictionaries 43 | .idea/libraries 44 | .idea/caches 45 | 46 | # Keystore files 47 | # Uncomment the following lines if you do not want to check your keystore files in. 48 | #*.jks 49 | #*.keystore 50 | 51 | # External native build folder generated in Android Studio 2.2 and later 52 | .externalNativeBuild 53 | 54 | # Google Services (e.g. APIs or Firebase) 55 | google-services.json 56 | 57 | # Freeline 58 | freeline.py 59 | freeline/ 60 | freeline_project_description.json 61 | 62 | # fastlane 63 | fastlane/report.xml 64 | fastlane/Preview.html 65 | fastlane/screenshots 66 | fastlane/test_output 67 | fastlane/readme.md 68 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 |
116 |
-------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CheckboxQuestion/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | -------------------------------------------------------------------------------- /CheckboxQuestion/.idea/.name: -------------------------------------------------------------------------------- 1 | LibraryCreate -------------------------------------------------------------------------------- /CheckboxQuestion/.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 |
116 |
-------------------------------------------------------------------------------- /CheckboxQuestion/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 21 | 22 | -------------------------------------------------------------------------------- /CheckboxQuestion/.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /CheckboxQuestion/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /CheckboxQuestion/.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /CheckboxQuestion/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CheckboxQuestion/CheckboxQuestion/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /CheckboxQuestion/CheckboxQuestion/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 30 5 | buildToolsVersion "30.0.3" 6 | 7 | defaultConfig { 8 | minSdkVersion 16 9 | targetSdkVersion 30 10 | versionCode 1 11 | versionName "1.0" 12 | 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | consumerProguardFiles "consumer-rules.pro" 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | implementation fileTree(dir: "libs", include: ["*.jar"]) 27 | implementation 'androidx.appcompat:appcompat:1.2.0' 28 | testImplementation 'junit:junit:4.12' 29 | androidTestImplementation 'androidx.test.ext:junit:1.1.2' 30 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 31 | 32 | } -------------------------------------------------------------------------------- /CheckboxQuestion/CheckboxQuestion/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EunoiaC/Checkbox-Questions/c4accf0037ab27b4af84abf9b26b7177b31f1011/CheckboxQuestion/CheckboxQuestion/consumer-rules.pro -------------------------------------------------------------------------------- /CheckboxQuestion/CheckboxQuestion/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /CheckboxQuestion/CheckboxQuestion/src/androidTest/java/com/aadyad/checkboxquestion/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.aadyad.checkboxquestion; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("com.aadyad.checkboxquestion.test", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /CheckboxQuestion/CheckboxQuestion/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | / 5 | -------------------------------------------------------------------------------- /CheckboxQuestion/CheckboxQuestion/src/main/java/com/aadyad/checkboxquestion/OnAnswerChangedListener.java: -------------------------------------------------------------------------------- 1 | package com.aadyad.checkboxquestion; 2 | 3 | import java.util.ArrayList; 4 | 5 | public interface OnAnswerChangedListener { 6 | public void onAnswerChanged(int selectedAnswerIndex, String selectedAnswerText); 7 | public void onAnswerChanged(ArrayList listOfSelectedAnswerIndexes); 8 | } 9 | -------------------------------------------------------------------------------- /CheckboxQuestion/CheckboxQuestion/src/main/java/com/aadyad/checkboxquestion/Question.java: -------------------------------------------------------------------------------- 1 | package com.aadyad.checkboxquestion; 2 | 3 | import android.util.Log; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class Question { 8 | 9 | //TODO: Create MultipleAnswerQuestions 10 | 11 | public static final String MULTIPLE_CHOICE_QUESTION = "MultipleChoiceQuestion"; 12 | public static final String YES_OR_NO_QUESTION = "YesOrNoQuestion"; 13 | public static final String MULTIPLE_ANSWER_QUESTION = "MultipleAnswerQuestion"; 14 | public static final int LEFT = 0; 15 | public static final int HORIZONTAL = 0; 16 | public static final int VERTICAL = 1; 17 | public static final int FULL_VERTICAL = 3; 18 | public static final int NO_ANSWER = 0; 19 | public static final int SPLIT_VERTICAL = 1; 20 | public static final int CENTER = 1; 21 | public static final int RIGHT = 2; 22 | public static final int AUTO = 2; 23 | 24 | String question; 25 | String type; 26 | int correctAnswer; 27 | ArrayList multipleCorrectAnswer; 28 | String[] options = new String[]{"Yes", "No"}; 29 | 30 | public Question(String question, int correctAnswer, String type, String... options) { 31 | this.question = question; 32 | this.type = type; 33 | if (options != null){ 34 | this.options = options; 35 | } 36 | this.correctAnswer = correctAnswer; 37 | } 38 | 39 | public Question(String question, ArrayList correctAnswer, String type, String... options) { 40 | this.question = question; 41 | this.type = type; 42 | if (options != null){ 43 | this.options = options; 44 | } 45 | this.multipleCorrectAnswer = correctAnswer; 46 | } 47 | 48 | public Question(String question, String correctAnswer, String type, String... options) { 49 | this.question = question; 50 | this.type = type; 51 | if (options != null){ 52 | this.options = options; 53 | } 54 | this.correctAnswer = getIndexOfString(correctAnswer) + 1; 55 | } 56 | 57 | private int getIndexOfString(String s) { 58 | for (int i = 0; i < options.length; i++) { 59 | if (options[i].equals(s)) { 60 | Log.d("Question", "getIndexOfString: " + i); 61 | return i; 62 | } 63 | } 64 | Log.d("TAG", "answer not found: " + s); 65 | return -1; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /CheckboxQuestion/CheckboxQuestion/src/main/java/com/aadyad/checkboxquestion/QuestionList.java: -------------------------------------------------------------------------------- 1 | package com.aadyad.checkboxquestion; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | import android.view.View; 6 | import android.widget.LinearLayout; 7 | 8 | import com.aadyad.checkboxquestion.Views.MultipleAnswerQuestion; 9 | import com.aadyad.checkboxquestion.Views.MultipleChoiceQuestion; 10 | import com.aadyad.checkboxquestion.Views.YesOrNoQuestion; 11 | 12 | import java.util.ArrayList; 13 | import java.util.Arrays; 14 | import java.util.Collections; 15 | 16 | public class QuestionList { 17 | 18 | String[] questions; 19 | ArrayList choiceQuestions; 20 | LinearLayout linearLayout; 21 | QuestionListSettings settings; 22 | Context context; 23 | int orientation; 24 | 25 | public QuestionList(ArrayList questions, QuestionListSettings settings, Context context) { 26 | choiceQuestions = questions; 27 | this.settings = settings; 28 | this.context = context; 29 | this.orientation = settings.getCheckBoxOrientation(); 30 | linearLayout = new LinearLayout(context); 31 | } 32 | 33 | public QuestionList(String[] questions, QuestionListSettings settings, Context context) { 34 | this.questions = questions; 35 | this.settings = settings; 36 | this.orientation = settings.getCheckBoxOrientation(); 37 | this.context = context; 38 | linearLayout = new LinearLayout(context); 39 | } 40 | 41 | public void createQuestionViews() { 42 | int i = 1; 43 | linearLayout = new LinearLayout(context); 44 | linearLayout.setOrientation(LinearLayout.VERTICAL); 45 | if (questions == null) { 46 | for (Question q : choiceQuestions) { 47 | switch (q.type) { 48 | case Question.MULTIPLE_CHOICE_QUESTION: 49 | Log.d("TAG", "createQuestionViews: " + Arrays.toString(q.options)); 50 | MultipleChoiceQuestion multipleChoiceQuestion = new MultipleChoiceQuestion(context); 51 | multipleChoiceQuestion.init(q.question, String.valueOf(i), settings.isNumEnabled(), settings.getSpacing(), this.orientation, settings.getCheckBoxLocation(), settings.getQuestionTextSize(), settings.getCheckBoxTextSize(), q.correctAnswer, q.options); 52 | linearLayout.addView(multipleChoiceQuestion); 53 | break; 54 | case Question.YES_OR_NO_QUESTION: 55 | YesOrNoQuestion yesOrNoQuestion = new YesOrNoQuestion(context); 56 | yesOrNoQuestion.init(q.question, String.valueOf(i), settings.isNumEnabled(), settings.getSpacing(), this.orientation, settings.getCheckBoxLocation(), settings.getQuestionTextSize(), settings.getCheckBoxTextSize(), q.correctAnswer); 57 | linearLayout.addView(yesOrNoQuestion); 58 | break; 59 | case Question.MULTIPLE_ANSWER_QUESTION: 60 | MultipleAnswerQuestion multipleAnswerQuestion = new MultipleAnswerQuestion(context); 61 | multipleAnswerQuestion.init(q.question, String.valueOf(i), settings.isNumEnabled(), settings.getSpacing(), this.orientation, settings.getCheckBoxLocation(), settings.getQuestionTextSize(), settings.getCheckBoxTextSize(), q.options); 62 | multipleAnswerQuestion.setCorrectAnswer(q.multipleCorrectAnswer); 63 | linearLayout.addView(multipleAnswerQuestion); 64 | break; 65 | default: 66 | throw new RuntimeException("Type " + q.type + " does not exist."); 67 | } 68 | i++; 69 | } 70 | } else { 71 | for (String q : questions) { 72 | i++; 73 | YesOrNoQuestion yesOrNoQuestion = new YesOrNoQuestion(context); 74 | yesOrNoQuestion.init(q, String.valueOf(i), settings.isNumEnabled(), settings.getSpacing(), this.orientation, settings.getCheckBoxLocation(), settings.getQuestionTextSize(), settings.getCheckBoxTextSize(), Question.NO_ANSWER); 75 | linearLayout.addView(yesOrNoQuestion); 76 | } 77 | } 78 | 79 | } 80 | 81 | public void setLayoutOrientation(int orientation) { 82 | this.orientation = orientation; 83 | for (int i = 0; i < linearLayout.getChildCount(); i++) { 84 | YesOrNoQuestion yesOrNoQuestion; 85 | MultipleChoiceQuestion multipleChoiceQuestion; 86 | MultipleAnswerQuestion multipleAnswerQuestion; 87 | 88 | try { 89 | yesOrNoQuestion = (YesOrNoQuestion) getQuestion(i); 90 | yesOrNoQuestion.setCheckboxOrientation(orientation); 91 | } catch (ClassCastException ignored) { 92 | 93 | } 94 | 95 | try { 96 | multipleChoiceQuestion = (MultipleChoiceQuestion) getQuestion(i); 97 | multipleChoiceQuestion.setCheckboxOrientation(orientation); 98 | } catch (ClassCastException ignored) { 99 | 100 | } 101 | 102 | try { 103 | multipleAnswerQuestion = (MultipleAnswerQuestion) getQuestion(i); 104 | multipleAnswerQuestion.setCheckboxOrientation(orientation); 105 | } catch (ClassCastException ignored) { 106 | 107 | } 108 | } 109 | createQuestionViews(); 110 | } 111 | 112 | public float getPercentageOfCorrectAnswers() { 113 | int correctAnswers = 0; 114 | int allAnswers = linearLayout.getChildCount(); 115 | for (int i = 0; i < linearLayout.getChildCount(); i++) { 116 | YesOrNoQuestion yesOrNoQuestion; 117 | MultipleChoiceQuestion multipleChoiceQuestion; 118 | MultipleAnswerQuestion multipleAnswerQuestion; 119 | 120 | try { 121 | yesOrNoQuestion = (YesOrNoQuestion) getQuestion(i); 122 | int answer = yesOrNoQuestion.getSelectedAnswer(); 123 | Log.d("TAG", "answer: " + answer); 124 | int correctAnswer = choiceQuestions.get(i).correctAnswer; 125 | Log.d("TAG", "correct answer: " + correctAnswer); 126 | if (correctAnswer == Question.NO_ANSWER) { 127 | allAnswers--; 128 | } else if (answer == correctAnswer) { 129 | correctAnswers++; 130 | } 131 | } catch (ClassCastException ignored) { 132 | 133 | } 134 | 135 | try { 136 | multipleChoiceQuestion = (MultipleChoiceQuestion) getQuestion(i); 137 | int answer = multipleChoiceQuestion.getSelectedAnswer(); 138 | Log.d("TAG", "answer: " + answer); 139 | int correctAnswer = choiceQuestions.get(i).correctAnswer; 140 | Log.d("TAG", "correct answer: " + correctAnswer); 141 | if (correctAnswer == Question.NO_ANSWER) { 142 | allAnswers--; 143 | } else if (answer == correctAnswer) { 144 | correctAnswers++; 145 | } 146 | } catch (Exception ignored) { 147 | 148 | } 149 | 150 | try { 151 | multipleAnswerQuestion = (MultipleAnswerQuestion) getQuestion(i); 152 | ArrayList answer = multipleAnswerQuestion.getSelectedAnswers(); 153 | Collections.sort(answer); 154 | Log.d("TAG", "answer: " + answer); 155 | ArrayList correctAnswer = choiceQuestions.get(i).multipleCorrectAnswer; 156 | Collections.sort(correctAnswer); 157 | Log.d("TAG", "correct answer: " + correctAnswer); 158 | if (correctAnswer.size() == Question.NO_ANSWER || correctAnswer == null) { 159 | allAnswers--; 160 | } else if (answer.equals(correctAnswer)) { 161 | correctAnswers++; 162 | } 163 | } catch (ClassCastException ignored) { 164 | 165 | } 166 | } 167 | Log.d("TAG", "getPercentageOfCorrectAnswers: " + correctAnswers); 168 | Log.d("TAG", "getPercentageOfCorrectAnswers: " + allAnswers); 169 | return (float) correctAnswers / allAnswers; 170 | } 171 | 172 | public ArrayList getSelectedAnswers() { 173 | ArrayList answers = new ArrayList<>(); 174 | Log.d("answers", "list size: " + linearLayout.getChildCount()); 175 | for (int i = 0; i < linearLayout.getChildCount(); i++) { 176 | YesOrNoQuestion yesOrNoQuestion; 177 | MultipleChoiceQuestion multipleChoiceQuestion; 178 | MultipleAnswerQuestion multipleAnswerQuestion; 179 | 180 | try { 181 | yesOrNoQuestion = (YesOrNoQuestion) getQuestion(i); 182 | answers.add(yesOrNoQuestion.getSelectedAnswer()); 183 | } catch (ClassCastException ignored) { 184 | 185 | } 186 | 187 | try { 188 | multipleChoiceQuestion = (MultipleChoiceQuestion) getQuestion(i); 189 | answers.add(multipleChoiceQuestion.getSelectedAnswer()); 190 | } catch (Exception ignored) { 191 | 192 | } 193 | 194 | try { 195 | multipleAnswerQuestion = (MultipleAnswerQuestion) getQuestion(i); 196 | answers.add(multipleAnswerQuestion.getSelectedAnswers()); 197 | } catch (Exception ignored) { 198 | 199 | } 200 | } 201 | return answers; 202 | } 203 | 204 | public boolean areAllQuestionsAnswered() { 205 | Log.d("answers", "list size: " + linearLayout.getChildCount()); 206 | for (int i = 0; i < linearLayout.getChildCount(); i++) { 207 | YesOrNoQuestion yesOrNoQuestion; 208 | MultipleChoiceQuestion multipleChoiceQuestion; 209 | MultipleAnswerQuestion multipleAnswerQuestion; 210 | 211 | try { 212 | yesOrNoQuestion = (YesOrNoQuestion) getQuestion(i); 213 | if (yesOrNoQuestion.getSelectedAnswer() == 0) { 214 | return false; 215 | } 216 | } catch (ClassCastException ignored) { 217 | 218 | } 219 | try { 220 | multipleChoiceQuestion = (MultipleChoiceQuestion) getQuestion(i); 221 | if (multipleChoiceQuestion.getSelectedAnswer() == 0) { 222 | return false; 223 | } 224 | } catch (Exception ignored) { 225 | 226 | } 227 | 228 | try { 229 | multipleAnswerQuestion = (MultipleAnswerQuestion) getQuestion(i); 230 | if (multipleAnswerQuestion.getSelectedAnswers().size() == 0) { 231 | return false; 232 | } 233 | } catch (Exception ignored) { 234 | 235 | } 236 | } 237 | return true; 238 | } 239 | 240 | public View getQuestion(int index) { 241 | YesOrNoQuestion yesOrNoQuestion = null; 242 | MultipleChoiceQuestion multipleChoiceQuestion = null; 243 | MultipleAnswerQuestion multipleAnswerQuestion = null; 244 | View v = linearLayout.getChildAt(index); 245 | try { 246 | yesOrNoQuestion = (YesOrNoQuestion) v; 247 | } catch (ClassCastException ignored) { 248 | 249 | } 250 | 251 | try { 252 | multipleChoiceQuestion = (MultipleChoiceQuestion) v; 253 | } catch (Exception ignored) { 254 | 255 | } 256 | 257 | try { 258 | multipleAnswerQuestion = (MultipleAnswerQuestion) v; 259 | } catch (Exception ignored) { 260 | 261 | } 262 | 263 | if (yesOrNoQuestion != null) { 264 | return yesOrNoQuestion; 265 | } else if (multipleChoiceQuestion != null) { 266 | return multipleChoiceQuestion; 267 | } else if (multipleAnswerQuestion != null) { 268 | return multipleAnswerQuestion; 269 | } else { 270 | return null; 271 | } 272 | } 273 | 274 | public void addOnAnswerChangedListener(int index, OnAnswerChangedListener r) { 275 | try { 276 | ((MultipleChoiceQuestion) getQuestion(index)).addOnAnswerChangedListener(r); 277 | } catch (Exception ignored) { 278 | 279 | } 280 | 281 | try { 282 | ((MultipleAnswerQuestion) getQuestion(index)).addOnAnswerChangedListener(r); 283 | } catch (Exception ignored) { 284 | 285 | } 286 | 287 | try { 288 | ((YesOrNoQuestion) getQuestion(index)).addOnAnswerChangedListener(r); 289 | } catch (Exception ignored) { 290 | 291 | } 292 | } 293 | 294 | public LinearLayout getQuestionViews() { 295 | return linearLayout; 296 | } 297 | } 298 | -------------------------------------------------------------------------------- /CheckboxQuestion/CheckboxQuestion/src/main/java/com/aadyad/checkboxquestion/QuestionListSettings.java: -------------------------------------------------------------------------------- 1 | package com.aadyad.checkboxquestion; 2 | 3 | import android.view.Gravity; 4 | import android.widget.LinearLayout; 5 | 6 | public class QuestionListSettings { 7 | 8 | public static final int TEXT_SIZE_DEFAULT = -1; 9 | public static final int TEXT_SIZE_AUTO = -2; 10 | 11 | private int checkBoxLocation; 12 | private float optionLayoutHeight; 13 | private int checkBoxOrientation; 14 | private int spacing; 15 | private float questionTextSize; 16 | private float checkBoxTextSize; 17 | private float questionLayoutHeight; 18 | 19 | public float getQuestionTextSize() { 20 | return questionTextSize; 21 | } 22 | 23 | public void setQuestionTextSize(float questionTextSize) { 24 | this.questionTextSize = questionTextSize; 25 | } 26 | 27 | public float getCheckBoxTextSize() { 28 | return checkBoxTextSize; 29 | } 30 | 31 | public void setCheckBoxTextSize(float checkBoxTextSize) { 32 | this.checkBoxTextSize = checkBoxTextSize; 33 | } 34 | 35 | 36 | 37 | public float getTextSize() { 38 | return questionTextSize; 39 | } 40 | 41 | public void setTextSize(int textSize) { 42 | this.questionTextSize = textSize; 43 | } 44 | 45 | public float getOptionLayoutHeight() { 46 | return optionLayoutHeight; 47 | } 48 | 49 | public float getQuestionLayoutHeight() { 50 | return questionLayoutHeight; 51 | } 52 | 53 | public void setTextHeight(int textHeight) { 54 | this.questionLayoutHeight = textHeight; 55 | } 56 | 57 | private boolean numEnabled; 58 | 59 | public QuestionListSettings(SettingsBuilder builder){ 60 | checkBoxLocation = builder.checkBoxLocation; 61 | optionLayoutHeight = builder.optionLayoutHeight; 62 | checkBoxOrientation = builder.checkBoxOrientation; 63 | questionTextSize = builder.questionTextSize; 64 | questionLayoutHeight = builder.questionLayoutHeight; 65 | spacing = builder.spacing; 66 | numEnabled = builder.numEnabled; 67 | checkBoxTextSize = builder.optionBoxTextSize; 68 | } 69 | 70 | public int getCheckBoxLocation() { 71 | return checkBoxLocation; 72 | } 73 | 74 | public void setCheckBoxLocation(int checkBoxLocation) { 75 | this.checkBoxLocation = checkBoxLocation; 76 | } 77 | 78 | public int getCheckBoxOrientation() { 79 | return checkBoxOrientation; 80 | } 81 | 82 | public void setCheckBoxOrientation(int checkBoxOrientation) { 83 | this.checkBoxOrientation = checkBoxOrientation; 84 | } 85 | 86 | public int getSpacing() { 87 | return spacing; 88 | } 89 | 90 | public void setSpacing(int spacing) { 91 | this.spacing = spacing; 92 | } 93 | 94 | public boolean isNumEnabled() { 95 | return numEnabled; 96 | } 97 | 98 | public void setNumEnabled(boolean numEnabled) { 99 | this.numEnabled = numEnabled; 100 | } 101 | 102 | public static class SettingsBuilder { 103 | private int checkBoxLocation = Gravity.LEFT; 104 | private int checkBoxOrientation = LinearLayout.HORIZONTAL; 105 | private int spacing = 15; 106 | private boolean numEnabled = true; 107 | private float questionTextSize = QuestionListSettings.TEXT_SIZE_DEFAULT; 108 | private float optionBoxTextSize = QuestionListSettings.TEXT_SIZE_DEFAULT; 109 | private float questionLayoutHeight = QuestionListSettings.TEXT_SIZE_DEFAULT; 110 | private float optionLayoutHeight = QuestionListSettings.TEXT_SIZE_DEFAULT; 111 | 112 | 113 | public SettingsBuilder setCheckboxLocation(final int checkBoxLocation) { 114 | this.checkBoxLocation = checkBoxLocation; 115 | return this; 116 | } 117 | 118 | public SettingsBuilder setQuestionTextSize(final float textSize) { 119 | this.questionTextSize = textSize; 120 | return this; 121 | } 122 | 123 | public SettingsBuilder setOptionLayoutHeight(final float optionHeight) { 124 | this.optionLayoutHeight = optionHeight; 125 | return this; 126 | } 127 | 128 | public SettingsBuilder setQuestionLayoutHeight(final float questionHeight) { 129 | this.questionLayoutHeight = questionHeight; 130 | return this; 131 | } 132 | 133 | public SettingsBuilder setOptionTextSize(final float textSize) { 134 | this.optionBoxTextSize = textSize; 135 | return this; 136 | } 137 | 138 | public SettingsBuilder setCheckBoxOrientation(final int checkBoxOrientation) { 139 | this.checkBoxOrientation = checkBoxOrientation; 140 | return this; 141 | } 142 | 143 | public SettingsBuilder setSpacing(final int spacing) { 144 | this.spacing = spacing; 145 | return this; 146 | } 147 | 148 | public SettingsBuilder setNumberEnabled(final boolean numEnabled) { 149 | this.numEnabled = numEnabled; 150 | return this; 151 | } 152 | 153 | public QuestionListSettings create() { 154 | return new QuestionListSettings(this); 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /CheckboxQuestion/CheckboxQuestion/src/main/java/com/aadyad/checkboxquestion/Views/MultipleAnswerQuestion.java: -------------------------------------------------------------------------------- 1 | package com.aadyad.checkboxquestion.Views; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.util.Log; 7 | import android.view.Gravity; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.CheckBox; 12 | import android.widget.CompoundButton; 13 | import android.widget.LinearLayout; 14 | import android.widget.TextView; 15 | 16 | import androidx.annotation.Nullable; 17 | 18 | import com.aadyad.checkboxquestion.OnAnswerChangedListener; 19 | import com.aadyad.checkboxquestion.Question; 20 | import com.aadyad.checkboxquestion.QuestionListSettings; 21 | import com.aadyad.checkboxquestion.R; 22 | 23 | import java.util.ArrayList; 24 | import java.util.Arrays; 25 | import java.util.Collections; 26 | 27 | public class MultipleAnswerQuestion extends LinearLayout { 28 | 29 | public static final int LEFT = 0; 30 | public static final int CENTER = 1; 31 | public static final int RIGHT = 2; 32 | Context context; 33 | 34 | String[] allOptions; 35 | 36 | private OnAnswerChangedListener onAnswerChangedListener; 37 | 38 | ArrayList checkBoxes = new ArrayList<>(); 39 | ArrayList selectedAnswers; 40 | 41 | LinearLayout layout; 42 | LinearLayout mainLayout; 43 | private int spacing; 44 | private ArrayList correctAnswer; 45 | 46 | public MultipleAnswerQuestion(Context context) { 47 | this(context, null); 48 | this.context = context; 49 | this.onAnswerChangedListener = null; 50 | } 51 | 52 | public MultipleAnswerQuestion(Context context, @Nullable AttributeSet attrs) { 53 | super(context, attrs); 54 | this.context = context; 55 | this.onAnswerChangedListener = null; 56 | 57 | setOrientation(LinearLayout.VERTICAL); 58 | LayoutInflater.from(context).inflate(R.layout.multiple_answer_question, this, true); 59 | 60 | String title; 61 | String number; 62 | String a1; 63 | String a2; 64 | String a3; 65 | String a4; 66 | int spacing; 67 | float questionTextSize, optionTextSize; 68 | int boxLocation; 69 | int orientation; 70 | boolean numberEnabled; 71 | TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MultipleAnswerQuestion, 0, 0); 72 | 73 | try { 74 | //optionLayoutHeight = a.getFloat(R.styleable.MultipleAnswerQuestion_option_layout_height, QuestionListSettings.TEXT_SIZE_DEFAULT); 75 | questionTextSize = a.getFloat(R.styleable.MultipleAnswerQuestion_question_text_size, QuestionListSettings.TEXT_SIZE_DEFAULT); 76 | optionTextSize = a.getFloat(R.styleable.MultipleAnswerQuestion_option_text_size, QuestionListSettings.TEXT_SIZE_DEFAULT); 77 | //questionLayoutHeight = a.getFloat(R.styleable.MultipleAnswerQuestion_question_layout_height, QuestionListSettings.TEXT_SIZE_DEFAULT); 78 | a1 = a.getString(R.styleable.MultipleAnswerQuestion_option_1); 79 | a2 = a.getString(R.styleable.MultipleAnswerQuestion_option_2); 80 | a3 = a.getString(R.styleable.MultipleAnswerQuestion_option_3); 81 | a4 = a.getString(R.styleable.MultipleAnswerQuestion_option_4); 82 | title = a.getString(R.styleable.MultipleAnswerQuestion_question_title); 83 | boxLocation = a.getInt(R.styleable.MultipleAnswerQuestion_checkbox_location, 0); 84 | orientation = a.getInt(R.styleable.MultipleAnswerQuestion_checkbox_orientation, 0); 85 | spacing = a.getInt(R.styleable.MultipleAnswerQuestion_spacing_between_boxes, 17); 86 | number = a.getString(R.styleable.MultipleAnswerQuestion_question_number); 87 | numberEnabled = a.getBoolean(R.styleable.MultipleAnswerQuestion_number_enabled, true); 88 | } finally { 89 | a.recycle(); 90 | } 91 | 92 | init(title, number, numberEnabled, spacing, orientation, boxLocation, questionTextSize, optionTextSize, a1, a2, a3, a4); 93 | } 94 | 95 | // Setup views 96 | public void init(String title, String number, boolean numEnabled, int spacing, int orientation, int boxLocation, float questionTextSize, float optionTextSize, String... options) { 97 | TextView questionNumber = (TextView) findViewById(R.id.question_number); 98 | final CheckBox option1 = (CheckBox) findViewById(R.id.answer1); 99 | final CheckBox option2 = (CheckBox) findViewById(R.id.answer2); 100 | final CheckBox option3 = (CheckBox) findViewById(R.id.answer3); 101 | final CheckBox option4 = (CheckBox) findViewById(R.id.answer4); 102 | 103 | selectedAnswers = new ArrayList<>(); 104 | 105 | layout = findViewById(R.id.multipleChoiceHolder); 106 | mainLayout = findViewById(R.id.mainLayout); 107 | 108 | this.spacing = spacing; 109 | this.allOptions = options; 110 | 111 | checkBoxes.add(option1); 112 | checkBoxes.add(option2); 113 | checkBoxes.add(option3); 114 | checkBoxes.add(option4); 115 | 116 | setQuestionTextSize(questionTextSize); 117 | setOptionTextSize(optionTextSize); 118 | 119 | Log.d("TAG", "init: " + Arrays.toString(options)); 120 | 121 | String a1 = ""; 122 | String a2 = ""; 123 | String a3 = ""; 124 | String a4 = ""; 125 | 126 | try { 127 | a1 = options[0]; 128 | a2 = options[1]; 129 | a3 = options[2]; 130 | a4 = options[3]; 131 | } catch (Exception ignored) { 132 | 133 | } 134 | 135 | option1.setText(a1); 136 | option2.setText(a2); 137 | option3.setText(a3); 138 | option4.setText(a4); 139 | 140 | LinearLayout templayout = null; 141 | 142 | if (options.length > 4){ 143 | Log.d("TAG", "init: length greater than 4"); 144 | for (int i = 4; i < options.length; i++){ 145 | 146 | if (templayout == null){ 147 | templayout = new LinearLayout(context); 148 | templayout.setOrientation(HORIZONTAL); 149 | } 150 | 151 | if (orientation == Question.HORIZONTAL){ 152 | throw new RuntimeException("Cannot have more than 4 options when horizontal. Try split_vertical or vertical."); 153 | } else if (orientation == Question.SPLIT_VERTICAL){ 154 | Log.d("TAG", "init: " + templayout.getChildCount()); 155 | if (templayout.getChildCount() == 0){ 156 | Log.d("TAG", "init: child count 0"); 157 | View spacer = new View(context); 158 | spacer.setLayoutParams(new ViewGroup.LayoutParams(0, spacing)); 159 | layout.addView(spacer); 160 | 161 | //Creating new checkbox 162 | final CheckBox checkBox = new CheckBox(context); 163 | checkBox.setTextSize(optionTextSize); 164 | checkBox.setText(options[i]); 165 | checkBoxes.add(checkBox); 166 | final int finalI = i; 167 | 168 | checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 169 | @Override 170 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 171 | Integer selectedAnswer = finalI + 1; 172 | if (isChecked){ 173 | //Add selected answer to integer arraylist 174 | selectedAnswers.add(selectedAnswer); 175 | } else{ 176 | //Remove selected answer to integer arraylist 177 | selectedAnswers.remove(selectedAnswer); 178 | } 179 | if (onAnswerChangedListener != null) { 180 | onAnswerChangedListener.onAnswerChanged(selectedAnswers); 181 | } 182 | } 183 | }); 184 | 185 | templayout.addView(checkBox); 186 | View v = new View(context); 187 | ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(spacing, 0); 188 | v.setLayoutParams(params); 189 | templayout.addView(v); 190 | 191 | try { 192 | String s = options[i + 1]; 193 | } catch (Exception e) { 194 | e.printStackTrace(); 195 | layout.addView(templayout); 196 | } 197 | } else if (templayout.getChildCount() == 2){ 198 | Log.d("TAG", "init: child count 2"); 199 | 200 | //Creating new checkbox 201 | final CheckBox checkBox = new CheckBox(context); 202 | checkBox.setTextSize(optionTextSize); 203 | checkBox.setText(options[i]); 204 | checkBoxes.add(checkBox); 205 | final int finalI = i; 206 | 207 | checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 208 | @Override 209 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 210 | Integer selectedAnswer = finalI + 1; 211 | if (isChecked){ 212 | //Add selected answer to integer arraylist 213 | selectedAnswers.add(selectedAnswer); 214 | } else{ 215 | //Remove selected answer to integer arraylist 216 | selectedAnswers.remove(selectedAnswer); 217 | } 218 | if (onAnswerChangedListener != null) { 219 | onAnswerChangedListener.onAnswerChanged(selectedAnswers); 220 | } 221 | } 222 | }); 223 | 224 | templayout.addView(checkBox); 225 | layout.addView(templayout); 226 | templayout = null; 227 | } 228 | } else if (orientation == Question.FULL_VERTICAL){ 229 | Log.d("TAG", "init: " + templayout.getChildCount()); 230 | if (templayout.getChildCount() == 0){ 231 | Log.d("TAG", "init: child count 0"); 232 | 233 | //Creating new checkbox 234 | final CheckBox checkBox = new CheckBox(context); 235 | checkBox.setTextSize(optionTextSize); 236 | checkBox.setText(options[i]); 237 | checkBoxes.add(checkBox); 238 | final int finalI = i; 239 | 240 | checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 241 | @Override 242 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 243 | Integer selectedAnswer = finalI + 1; 244 | if (isChecked){ 245 | //Add selected answer to integer arraylist 246 | selectedAnswers.add(selectedAnswer); 247 | } else{ 248 | //Remove selected answer to integer arraylist 249 | selectedAnswers.remove(selectedAnswer); 250 | } 251 | if (onAnswerChangedListener != null) { 252 | onAnswerChangedListener.onAnswerChanged(selectedAnswers); 253 | } 254 | } 255 | }); 256 | 257 | templayout.addView(checkBox); 258 | View v = new View(context); 259 | ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(0, spacing); 260 | v.setLayoutParams(params); 261 | layout.addView(v); 262 | layout.addView(templayout); 263 | templayout = null; 264 | } 265 | } 266 | } 267 | } 268 | 269 | // if (a1 == null || a2 == null){ 270 | // throw new RuntimeException("A MultipleAnswerQuestion must have 2 or more options!"); 271 | // } 272 | 273 | if (a3 == null) { 274 | option3.setVisibility(GONE); 275 | } else{ 276 | option3.setVisibility(VISIBLE); 277 | } 278 | if (a4 == null) { 279 | option4.setVisibility(GONE); 280 | } else{ 281 | option4.setVisibility(VISIBLE); 282 | } 283 | 284 | if (option4.getText().toString().equals("")){ 285 | option4.setVisibility(GONE); 286 | } 287 | if (option3.getText().toString().equals("")){ 288 | option3.setVisibility(GONE); 289 | } 290 | 291 | //Todo: add option to choose location of question text 292 | 293 | setCheckBoxLocation(boxLocation); 294 | 295 | setCheckboxOrientation(orientation); 296 | 297 | setQuestion(title); 298 | if (numEnabled) { 299 | setQuestionNumber(number); 300 | questionNumber.setVisibility(VISIBLE); 301 | } else { 302 | questionNumber.setVisibility(GONE); 303 | } 304 | 305 | onFinishInflate(); 306 | } 307 | 308 | private void setCheckBoxLocation(int location) { 309 | if (location == LEFT){ 310 | mainLayout.setGravity(Gravity.LEFT); 311 | } else if (location == CENTER){ 312 | mainLayout.setGravity(Gravity.CENTER); 313 | } else if (location == RIGHT){ 314 | mainLayout.setGravity(Gravity.RIGHT); 315 | } 316 | } 317 | 318 | @Override 319 | protected void onFinishInflate() { 320 | super.onFinishInflate(); 321 | final CheckBox option1 = (CheckBox) findViewById(R.id.answer1); 322 | final CheckBox option2 = (CheckBox) findViewById(R.id.answer2); 323 | final CheckBox option3 = (CheckBox) findViewById(R.id.answer3); 324 | final CheckBox option4 = (CheckBox) findViewById(R.id.answer4); 325 | 326 | option1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 327 | @Override 328 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 329 | Integer selectedAnswer = 1; 330 | if (isChecked){ 331 | //Add selected answer to integer arraylist 332 | selectedAnswers.add(selectedAnswer); 333 | } else{ 334 | //Remove selected answer to integer arraylist 335 | selectedAnswers.remove(selectedAnswer); 336 | } 337 | if (onAnswerChangedListener != null) { 338 | onAnswerChangedListener.onAnswerChanged(selectedAnswers); 339 | } 340 | } 341 | }); 342 | 343 | option2.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 344 | @Override 345 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 346 | Integer selectedAnswer = 2; 347 | if (isChecked){ 348 | //Add selected answer to integer arraylist 349 | selectedAnswers.add(selectedAnswer); 350 | } else{ 351 | //Remove selected answer to integer arraylist 352 | selectedAnswers.remove(selectedAnswer); 353 | } 354 | if (onAnswerChangedListener != null) { 355 | onAnswerChangedListener.onAnswerChanged(selectedAnswers); 356 | } 357 | } 358 | }); 359 | 360 | option3.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 361 | @Override 362 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 363 | Integer selectedAnswer = 3; 364 | if (isChecked){ 365 | //Add selected answer to integer arraylist 366 | selectedAnswers.add(selectedAnswer); 367 | } else{ 368 | //Remove selected answer to integer arraylist 369 | selectedAnswers.remove(selectedAnswer); 370 | } 371 | if (onAnswerChangedListener != null) { 372 | onAnswerChangedListener.onAnswerChanged(selectedAnswers); 373 | } 374 | } 375 | }); 376 | 377 | option4.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 378 | @Override 379 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 380 | Integer selectedAnswer = 4; 381 | if (isChecked){ 382 | //Add selected answer to integer arraylist 383 | selectedAnswers.add(selectedAnswer); 384 | } else{ 385 | //Remove selected answer to integer arraylist 386 | selectedAnswers.remove(selectedAnswer); 387 | } 388 | if (onAnswerChangedListener != null) { 389 | onAnswerChangedListener.onAnswerChanged(selectedAnswers); 390 | } 391 | } 392 | }); 393 | } 394 | 395 | public ArrayList getSelectedAnswers() { 396 | return selectedAnswers; 397 | } 398 | 399 | public void setQuestion(String question) { 400 | TextView questionTitle = (TextView) findViewById(R.id.question_title); 401 | questionTitle.setText(question); 402 | } 403 | 404 | public void setOptionTextSize(float optionTextSize){ 405 | final CheckBox option1 = (CheckBox) findViewById(R.id.answer1); 406 | final CheckBox option2 = (CheckBox) findViewById(R.id.answer2); 407 | final CheckBox option3 = (CheckBox) findViewById(R.id.answer3); 408 | final CheckBox option4 = (CheckBox) findViewById(R.id.answer4); 409 | 410 | if (optionTextSize == QuestionListSettings.TEXT_SIZE_AUTO){ 411 | //Todo: add code to auto adjust size using textheight 412 | }else if (!(optionTextSize == QuestionListSettings.TEXT_SIZE_DEFAULT)){ 413 | option1.setTextSize(optionTextSize); 414 | option2.setTextSize(optionTextSize); 415 | option3.setTextSize(optionTextSize); 416 | option4.setTextSize(optionTextSize); 417 | } 418 | } 419 | 420 | public void setQuestionTextSize(float questionTextSize){ 421 | TextView questionNumber = (TextView) findViewById(R.id.question_number); 422 | TextView questionTitle = (TextView) findViewById(R.id.question_title); 423 | 424 | if (questionTextSize == QuestionListSettings.TEXT_SIZE_AUTO){ 425 | //Todo: add code to auto adjust size using height 426 | } else if (!(questionTextSize == QuestionListSettings.TEXT_SIZE_DEFAULT)){ 427 | questionTitle.setTextSize(questionTextSize); 428 | questionNumber.setTextSize(questionTextSize); 429 | } 430 | } 431 | 432 | public void setQuestionNumber(String number) { 433 | TextView questionNumber = (TextView) findViewById(R.id.question_number); 434 | questionNumber.setText(number + ". "); 435 | } 436 | 437 | public void setCheckboxOrientation(int orientation){ 438 | View spacing1 = findViewById(R.id.spacing1); 439 | View layoutSpacing = findViewById(R.id.spacingLayouts); 440 | View spacing2 = findViewById(R.id.spacing2); 441 | 442 | Log.d("Orientation", "setLayoutOrientation: " + orientation); 443 | 444 | ViewGroup.LayoutParams layoutParams1 = spacing1.getLayoutParams(); 445 | ViewGroup.LayoutParams layoutParams2 = spacing2.getLayoutParams(); 446 | ViewGroup.LayoutParams layoutParams3 = layoutSpacing.getLayoutParams(); 447 | 448 | if (orientation == Question.HORIZONTAL){ 449 | //Log.d("Orientation", "setLayoutOrientation: horizontal"); 450 | layoutParams1.width = spacing; 451 | layoutParams2.width = spacing; 452 | layoutParams3.width = spacing; 453 | layoutParams1.height = 0; 454 | layoutParams2.height = 0; 455 | layoutParams3.height= 0; 456 | layoutSpacing.setLayoutParams(layoutParams3); 457 | spacing1.setLayoutParams(layoutParams1); 458 | spacing2.setLayoutParams(layoutParams2); 459 | layout.setOrientation(HORIZONTAL); 460 | } else if (orientation == Question.SPLIT_VERTICAL){ 461 | layout.setOrientation(VERTICAL); 462 | layoutParams3.width = 0; 463 | layoutParams1.width = spacing; 464 | layoutParams2.width = spacing; 465 | layoutParams3.height = spacing; 466 | layoutParams1.height = 0; 467 | layoutParams2.height = 0; 468 | layoutSpacing.setLayoutParams(layoutParams3); 469 | spacing1.setLayoutParams(layoutParams1); 470 | spacing2.setLayoutParams(layoutParams2); 471 | } else if (orientation == Question.AUTO){ 472 | //Todo: code auto orientation if a question goes out of view 473 | } else if (orientation == Question.FULL_VERTICAL){ 474 | LinearLayout layout1 = findViewById(R.id.checkBoxHolder1); 475 | LinearLayout layout2 = findViewById(R.id.checkBoxHolder2); 476 | layout1.setOrientation(VERTICAL); 477 | layout2.setOrientation(VERTICAL); 478 | layout.setOrientation(VERTICAL); 479 | layoutParams3.width = 0; 480 | layoutParams1.width = 0; 481 | layoutParams2.width = 0; 482 | layoutParams3.height = spacing; 483 | layoutParams1.height = spacing; 484 | layoutParams2.height = spacing; 485 | layoutSpacing.setLayoutParams(layoutParams3); 486 | spacing1.setLayoutParams(layoutParams1); 487 | spacing2.setLayoutParams(layoutParams2); 488 | } 489 | } 490 | 491 | public void addOnAnswerChangedListener(OnAnswerChangedListener onAnswerChangedListener){ 492 | this.onAnswerChangedListener = onAnswerChangedListener; 493 | } 494 | 495 | public void setCheckedOption(int option){ 496 | for (int i = 0; i < checkBoxes.size(); i++){ 497 | if (i == option - 1){ 498 | checkBoxes.get(i).setChecked(true); 499 | break; 500 | } else{ 501 | checkBoxes.get(i).setChecked(false); 502 | } 503 | } 504 | } 505 | 506 | public void setCheckedOption(String option){ 507 | for (CheckBox checkBox : checkBoxes){ 508 | if (checkBox.getText().equals(option)){ 509 | checkBox.setChecked(true); 510 | break; 511 | } else{ 512 | checkBox.setChecked(false); 513 | } 514 | } 515 | } 516 | 517 | public void setOptionText(int index, String text){ 518 | checkBoxes.get(index).setText(text); 519 | } 520 | 521 | public CheckBox getCheckbox(int index){ 522 | return checkBoxes.get(index); 523 | } 524 | 525 | public TextView getQuestionTitleTextView(){ 526 | return findViewById(R.id.question_title); 527 | } 528 | 529 | public TextView getQuestionNumberTextView(){ 530 | return findViewById(R.id.question_number); 531 | } 532 | 533 | public String[] getOptions(){ 534 | return allOptions; 535 | } 536 | 537 | public void setCorrectAnswer(ArrayList correctAnswer){ 538 | Collections.sort(correctAnswer); 539 | this.correctAnswer = correctAnswer; 540 | } 541 | 542 | public ArrayList getCorrectAnswer(){ 543 | return correctAnswer; 544 | } 545 | 546 | public boolean isAnswerCorrect() throws Exception{ 547 | if (getCorrectAnswer() == null){ 548 | throw new Exception("There is no correct answer for this question."); 549 | } 550 | Collections.sort(selectedAnswers); 551 | return getCorrectAnswer().equals(selectedAnswers); 552 | } 553 | } 554 | -------------------------------------------------------------------------------- /CheckboxQuestion/CheckboxQuestion/src/main/java/com/aadyad/checkboxquestion/Views/MultipleChoiceQuestion.java: -------------------------------------------------------------------------------- 1 | package com.aadyad.checkboxquestion.Views; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.util.Log; 7 | import android.view.Gravity; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.CheckBox; 12 | import android.widget.LinearLayout; 13 | import android.widget.TextView; 14 | 15 | import androidx.annotation.Nullable; 16 | 17 | import com.aadyad.checkboxquestion.OnAnswerChangedListener; 18 | import com.aadyad.checkboxquestion.Question; 19 | import com.aadyad.checkboxquestion.QuestionListSettings; 20 | import com.aadyad.checkboxquestion.R; 21 | 22 | import java.util.ArrayList; 23 | import java.util.Arrays; 24 | 25 | public class MultipleChoiceQuestion extends LinearLayout { 26 | 27 | public static final int LEFT = 0; 28 | public static final int CENTER = 1; 29 | public static final int RIGHT = 2; 30 | String[] allOptions; 31 | Context context; 32 | 33 | private OnAnswerChangedListener onAnswerChangedListener; 34 | 35 | ArrayList checkBoxes = new ArrayList<>(); 36 | 37 | private int buttonClicked = 0; //0 is not clicked, 1 is no, 2 is yes 38 | LinearLayout layout; 39 | LinearLayout mainLayout; 40 | private int spacing; 41 | private int correctAnswer; 42 | 43 | public MultipleChoiceQuestion(Context context) { 44 | this(context, null); 45 | this.context = context; 46 | this.onAnswerChangedListener = null; 47 | } 48 | 49 | public MultipleChoiceQuestion(Context context, @Nullable AttributeSet attrs) { 50 | super(context, attrs); 51 | this.context = context; 52 | this.onAnswerChangedListener = null; 53 | setOrientation(LinearLayout.VERTICAL); 54 | LayoutInflater.from(context).inflate(R.layout.multiple_choice_question, this, true); 55 | 56 | String title; 57 | String number; 58 | String a1; 59 | String a2; 60 | String a3; 61 | String a4; 62 | int spacing; 63 | int tempCorrectAnswer; 64 | float questionTextSize, optionTextSize; 65 | int boxLocation; 66 | int orientation; 67 | boolean numberEnabled; 68 | TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MultipleChoiceQuestion, 0, 0); 69 | 70 | try { 71 | //optionLayoutHeight = a.getFloat(R.styleable.MultipleChoiceQuestion_option_layout_height, QuestionListSettings.TEXT_SIZE_DEFAULT); 72 | questionTextSize = a.getFloat(R.styleable.MultipleChoiceQuestion_question_text_size, QuestionListSettings.TEXT_SIZE_DEFAULT); 73 | optionTextSize = a.getFloat(R.styleable.MultipleChoiceQuestion_option_text_size, QuestionListSettings.TEXT_SIZE_DEFAULT); 74 | //questionLayoutHeight = a.getFloat(R.styleable.MultipleChoiceQuestion_question_layout_height, QuestionListSettings.TEXT_SIZE_DEFAULT); 75 | a1 = a.getString(R.styleable.MultipleChoiceQuestion_option_1); 76 | a2 = a.getString(R.styleable.MultipleChoiceQuestion_option_2); 77 | a3 = a.getString(R.styleable.MultipleChoiceQuestion_option_3); 78 | a4 = a.getString(R.styleable.MultipleChoiceQuestion_option_4); 79 | tempCorrectAnswer = a.getInt(R.styleable.MultipleChoiceQuestion_correct_answer, 0); 80 | title = a.getString(R.styleable.MultipleChoiceQuestion_question_title); 81 | boxLocation = a.getInt(R.styleable.MultipleChoiceQuestion_checkbox_location, 0); 82 | orientation = a.getInt(R.styleable.MultipleChoiceQuestion_checkbox_orientation, 0); 83 | spacing = a.getInt(R.styleable.MultipleChoiceQuestion_spacing_between_boxes, 17); 84 | number = a.getString(R.styleable.MultipleChoiceQuestion_question_number); 85 | numberEnabled = a.getBoolean(R.styleable.MultipleChoiceQuestion_number_enabled, true); 86 | } finally { 87 | a.recycle(); 88 | } 89 | 90 | init(title, number, numberEnabled, spacing, orientation, boxLocation, questionTextSize, optionTextSize, tempCorrectAnswer, a1, a2, a3, a4); 91 | } 92 | 93 | // Setup views 94 | public void init(String title, String number, boolean numEnabled, int spacing, int orientation, int boxLocation, float questionTextSize, float optionTextSize, int correctAnswer, String... options) { 95 | TextView questionTitle = (TextView) findViewById(R.id.question_title); 96 | TextView questionNumber = (TextView) findViewById(R.id.question_number); 97 | final CheckBox option1 = (CheckBox) findViewById(R.id.answer1); 98 | final CheckBox option2 = (CheckBox) findViewById(R.id.answer2); 99 | final CheckBox option3 = (CheckBox) findViewById(R.id.answer3); 100 | final CheckBox option4 = (CheckBox) findViewById(R.id.answer4); 101 | layout = findViewById(R.id.multipleChoiceHolder); 102 | mainLayout = findViewById(R.id.mainLayout); 103 | 104 | this.spacing = spacing; 105 | this.allOptions = options; 106 | this.correctAnswer = correctAnswer; 107 | 108 | checkBoxes.add(option1); 109 | checkBoxes.add(option2); 110 | checkBoxes.add(option3); 111 | checkBoxes.add(option4); 112 | 113 | setQuestionTextSize(questionTextSize); 114 | setOptionTextSize(optionTextSize); 115 | 116 | Log.d("TAG", "init: " + Arrays.toString(options)); 117 | 118 | String a1 = ""; 119 | String a2 = ""; 120 | String a3 = ""; 121 | String a4 = ""; 122 | 123 | try { 124 | a1 = options[0]; 125 | a2 = options[1]; 126 | a3 = options[2]; 127 | a4 = options[3]; 128 | } catch (Exception ignored) { 129 | 130 | } 131 | 132 | option1.setText(a1); 133 | option2.setText(a2); 134 | option3.setText(a3); 135 | option4.setText(a4); 136 | 137 | LinearLayout templayout = null; 138 | 139 | if (options.length > 4) { 140 | Log.d("TAG", "init: length greater than 4"); 141 | for (int i = 4; i < options.length; i++) { 142 | 143 | if (templayout == null) { 144 | templayout = new LinearLayout(context); 145 | templayout.setOrientation(HORIZONTAL); 146 | } 147 | 148 | if (orientation == Question.HORIZONTAL) { 149 | throw new RuntimeException("Cannot have more than 4 options when horizontal. Try split_vertical or vertical."); 150 | } else if (orientation == Question.SPLIT_VERTICAL) { 151 | Log.d("TAG", "init: " + templayout.getChildCount()); 152 | if (templayout.getChildCount() == 0) { 153 | Log.d("TAG", "init: child count 0"); 154 | View spacer = new View(context); 155 | spacer.setLayoutParams(new ViewGroup.LayoutParams(0, spacing)); 156 | layout.addView(spacer); 157 | 158 | //Creating new checkbox 159 | final CheckBox checkBox = new CheckBox(context); 160 | checkBox.setTextSize(optionTextSize); 161 | checkBox.setText(options[i]); 162 | checkBoxes.add(checkBox); 163 | final int finalI = i; 164 | 165 | checkBox.setOnClickListener(new OnClickListener() { 166 | @Override 167 | public void onClick(View v) { 168 | for (CheckBox checkBox1 : checkBoxes) { 169 | if (!checkBox1.equals(checkBox)) { 170 | checkBox1.setChecked(false); 171 | } else { 172 | checkBox1.setChecked(true); 173 | } 174 | } 175 | buttonClicked = finalI + 1; 176 | if (onAnswerChangedListener != null) { 177 | onAnswerChangedListener.onAnswerChanged(buttonClicked, checkBox.getText().toString()); 178 | } 179 | } 180 | }); 181 | 182 | templayout.addView(checkBox); 183 | View v = new View(context); 184 | ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(spacing, 0); 185 | v.setLayoutParams(params); 186 | templayout.addView(v); 187 | 188 | try { 189 | String s = options[i + 1]; 190 | } catch (Exception e) { 191 | e.printStackTrace(); 192 | layout.addView(templayout); 193 | } 194 | } else if (templayout.getChildCount() == 2) { 195 | Log.d("TAG", "init: child count 2"); 196 | 197 | //Creating new checkbox 198 | final CheckBox checkBox = new CheckBox(context); 199 | checkBox.setTextSize(optionTextSize); 200 | checkBox.setText(options[i]); 201 | checkBoxes.add(checkBox); 202 | final int finalI = i; 203 | checkBox.setOnClickListener(new OnClickListener() { 204 | @Override 205 | public void onClick(View v) { 206 | for (CheckBox checkBox1 : checkBoxes) { 207 | if (!checkBox1.equals(checkBox)) { 208 | checkBox1.setChecked(false); 209 | } else { 210 | checkBox1.setChecked(true); 211 | } 212 | } 213 | buttonClicked = finalI + 1; 214 | if (onAnswerChangedListener != null) { 215 | onAnswerChangedListener.onAnswerChanged(buttonClicked, checkBox.getText().toString()); 216 | } 217 | } 218 | }); 219 | 220 | templayout.addView(checkBox); 221 | layout.addView(templayout); 222 | templayout = null; 223 | } 224 | } else if (orientation == Question.FULL_VERTICAL) { 225 | Log.d("TAG", "init: " + templayout.getChildCount()); 226 | if (templayout.getChildCount() == 0) { 227 | Log.d("TAG", "init: child count 0"); 228 | 229 | //Creating new checkbox 230 | final CheckBox checkBox = new CheckBox(context); 231 | checkBox.setTextSize(optionTextSize); 232 | checkBox.setText(options[i]); 233 | checkBoxes.add(checkBox); 234 | final int finalI = i; 235 | checkBox.setOnClickListener(new OnClickListener() { 236 | @Override 237 | public void onClick(View v) { 238 | for (CheckBox checkBox1 : checkBoxes) { 239 | if (!checkBox1.equals(checkBox)) { 240 | checkBox1.setChecked(false); 241 | } else { 242 | checkBox1.setChecked(true); 243 | } 244 | } 245 | buttonClicked = finalI + 1; 246 | if (onAnswerChangedListener != null) { 247 | onAnswerChangedListener.onAnswerChanged(buttonClicked, checkBox.getText().toString()); 248 | } 249 | } 250 | }); 251 | 252 | templayout.addView(checkBox); 253 | View v = new View(context); 254 | ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(0, spacing); 255 | v.setLayoutParams(params); 256 | layout.addView(v); 257 | layout.addView(templayout); 258 | templayout = null; 259 | } 260 | } 261 | } 262 | } 263 | 264 | // if (a1 == null || a2 == null){ 265 | // throw new RuntimeException("A MultipleChoiceQuestion must have 2 or more options!"); 266 | // } 267 | 268 | if (a3 == null) { 269 | option3.setVisibility(GONE); 270 | } else { 271 | option3.setVisibility(VISIBLE); 272 | } 273 | if (a4 == null) { 274 | option4.setVisibility(GONE); 275 | } else { 276 | option4.setVisibility(VISIBLE); 277 | } 278 | 279 | if (option4.getText().toString().equals("")) { 280 | option4.setVisibility(GONE); 281 | } 282 | if (option3.getText().toString().equals("")) { 283 | option3.setVisibility(GONE); 284 | } 285 | 286 | //Todo: add option to choose location of question text 287 | 288 | setCheckBoxLocation(boxLocation); 289 | 290 | setCheckboxOrientation(orientation); 291 | 292 | setQuestion(title); 293 | if (numEnabled) { 294 | setQuestionNumber(number); 295 | questionNumber.setVisibility(VISIBLE); 296 | } else { 297 | questionNumber.setVisibility(GONE); 298 | } 299 | 300 | onFinishInflate(); 301 | } 302 | 303 | private void setCheckBoxLocation(int location) { 304 | if (location == LEFT) { 305 | mainLayout.setGravity(Gravity.LEFT); 306 | } else if (location == CENTER) { 307 | mainLayout.setGravity(Gravity.CENTER); 308 | } else if (location == RIGHT) { 309 | mainLayout.setGravity(Gravity.RIGHT); 310 | } 311 | } 312 | 313 | @Override 314 | protected void onFinishInflate() { 315 | super.onFinishInflate(); 316 | final CheckBox option1 = (CheckBox) findViewById(R.id.answer1); 317 | final CheckBox option2 = (CheckBox) findViewById(R.id.answer2); 318 | final CheckBox option3 = (CheckBox) findViewById(R.id.answer3); 319 | final CheckBox option4 = (CheckBox) findViewById(R.id.answer4); 320 | 321 | option1.setOnClickListener(new OnClickListener() { 322 | @Override 323 | public void onClick(View v) { 324 | for (CheckBox checkBox1 : checkBoxes) { 325 | if (!checkBox1.equals(option1)) { 326 | checkBox1.setChecked(false); 327 | } else { 328 | option1.setChecked(true); 329 | } 330 | } 331 | buttonClicked = 1; 332 | if (onAnswerChangedListener != null) { 333 | onAnswerChangedListener.onAnswerChanged(buttonClicked, option1.getText().toString()); 334 | } 335 | } 336 | }); 337 | 338 | option2.setOnClickListener(new OnClickListener() { 339 | @Override 340 | public void onClick(View v) { 341 | for (CheckBox checkBox1 : checkBoxes) { 342 | if (!checkBox1.equals(option2)) { 343 | if (checkBox1.isChecked()) { 344 | checkBox1.setChecked(false); 345 | } 346 | } else { 347 | checkBox1.setChecked(true); 348 | } 349 | } 350 | buttonClicked = 2; 351 | if (onAnswerChangedListener != null) { 352 | onAnswerChangedListener.onAnswerChanged(buttonClicked, option2.getText().toString()); 353 | } 354 | } 355 | }); 356 | 357 | option3.setOnClickListener(new OnClickListener() { 358 | @Override 359 | public void onClick(View v) { 360 | for (CheckBox checkBox1 : checkBoxes) { 361 | if (!checkBox1.equals(option3)) { 362 | if (checkBox1.isChecked()) { 363 | checkBox1.setChecked(false); 364 | } 365 | } else { 366 | checkBox1.setChecked(true); 367 | } 368 | } 369 | buttonClicked = 3; 370 | 371 | if (onAnswerChangedListener != null) { 372 | onAnswerChangedListener.onAnswerChanged(buttonClicked, option3.getText().toString()); 373 | } 374 | } 375 | }); 376 | 377 | option4.setOnClickListener(new OnClickListener() { 378 | @Override 379 | public void onClick(View v) { 380 | for (CheckBox checkBox1 : checkBoxes) { 381 | if (!checkBox1.equals(option4)) { 382 | if (checkBox1.isChecked()) { 383 | checkBox1.setChecked(false); 384 | } 385 | } else { 386 | checkBox1.setChecked(true); 387 | } 388 | } 389 | buttonClicked = 4; 390 | if (onAnswerChangedListener != null) { 391 | onAnswerChangedListener.onAnswerChanged(buttonClicked, option4.getText().toString()); 392 | } 393 | } 394 | }); 395 | } 396 | 397 | public int getSelectedAnswer() { 398 | return buttonClicked; 399 | } 400 | 401 | public void setQuestion(String question) { 402 | TextView questionTitle = (TextView) findViewById(R.id.question_title); 403 | questionTitle.setText(question); 404 | } 405 | 406 | public void setOptionTextSize(float optionTextSize) { 407 | final CheckBox option1 = (CheckBox) findViewById(R.id.answer1); 408 | final CheckBox option2 = (CheckBox) findViewById(R.id.answer2); 409 | final CheckBox option3 = (CheckBox) findViewById(R.id.answer3); 410 | final CheckBox option4 = (CheckBox) findViewById(R.id.answer4); 411 | 412 | if (optionTextSize == QuestionListSettings.TEXT_SIZE_AUTO) { 413 | //Todo: add code to auto adjust size using textheight 414 | } else if (!(optionTextSize == QuestionListSettings.TEXT_SIZE_DEFAULT)) { 415 | option1.setTextSize(optionTextSize); 416 | option2.setTextSize(optionTextSize); 417 | option3.setTextSize(optionTextSize); 418 | option4.setTextSize(optionTextSize); 419 | } 420 | } 421 | 422 | public void setQuestionTextSize(float questionTextSize) { 423 | TextView questionNumber = (TextView) findViewById(R.id.question_number); 424 | TextView questionTitle = (TextView) findViewById(R.id.question_title); 425 | 426 | if (questionTextSize == QuestionListSettings.TEXT_SIZE_AUTO) { 427 | //Todo: add code to auto adjust size using height 428 | } else if (!(questionTextSize == QuestionListSettings.TEXT_SIZE_DEFAULT)) { 429 | questionTitle.setTextSize(questionTextSize); 430 | questionNumber.setTextSize(questionTextSize); 431 | } 432 | } 433 | 434 | public void setQuestionNumber(String number) { 435 | TextView questionNumber = (TextView) findViewById(R.id.question_number); 436 | questionNumber.setText(number + ". "); 437 | } 438 | 439 | public void setCheckboxOrientation(int orientation) { 440 | View spacing1 = findViewById(R.id.spacing1); 441 | View layoutSpacing = findViewById(R.id.spacingLayouts); 442 | View spacing2 = findViewById(R.id.spacing2); 443 | 444 | Log.d("Orientation", "setLayoutOrientation: " + orientation); 445 | 446 | ViewGroup.LayoutParams layoutParams1 = spacing1.getLayoutParams(); 447 | ViewGroup.LayoutParams layoutParams2 = spacing2.getLayoutParams(); 448 | ViewGroup.LayoutParams layoutParams3 = layoutSpacing.getLayoutParams(); 449 | 450 | if (orientation == Question.HORIZONTAL) { 451 | //Log.d("Orientation", "setLayoutOrientation: horizontal"); 452 | layoutParams1.width = spacing; 453 | layoutParams2.width = spacing; 454 | layoutParams3.width = spacing; 455 | layoutParams1.height = 0; 456 | layoutParams2.height = 0; 457 | layoutParams3.height = 0; 458 | layoutSpacing.setLayoutParams(layoutParams3); 459 | spacing1.setLayoutParams(layoutParams1); 460 | spacing2.setLayoutParams(layoutParams2); 461 | layout.setOrientation(HORIZONTAL); 462 | } else if (orientation == Question.SPLIT_VERTICAL) { 463 | layout.setOrientation(VERTICAL); 464 | layoutParams3.width = 0; 465 | layoutParams1.width = spacing; 466 | layoutParams2.width = spacing; 467 | layoutParams3.height = spacing; 468 | layoutParams1.height = 0; 469 | layoutParams2.height = 0; 470 | layoutSpacing.setLayoutParams(layoutParams3); 471 | spacing1.setLayoutParams(layoutParams1); 472 | spacing2.setLayoutParams(layoutParams2); 473 | } else if (orientation == Question.AUTO) { 474 | //Todo: code auto orientation if a question goes out of view 475 | } else if (orientation == Question.FULL_VERTICAL) { 476 | LinearLayout layout1 = findViewById(R.id.checkBoxHolder1); 477 | LinearLayout layout2 = findViewById(R.id.checkBoxHolder2); 478 | layout1.setOrientation(VERTICAL); 479 | layout2.setOrientation(VERTICAL); 480 | layout.setOrientation(VERTICAL); 481 | layoutParams3.width = 0; 482 | layoutParams1.width = 0; 483 | layoutParams2.width = 0; 484 | layoutParams3.height = spacing; 485 | layoutParams1.height = spacing; 486 | layoutParams2.height = spacing; 487 | layoutSpacing.setLayoutParams(layoutParams3); 488 | spacing1.setLayoutParams(layoutParams1); 489 | spacing2.setLayoutParams(layoutParams2); 490 | } 491 | } 492 | 493 | public void addOnAnswerChangedListener(OnAnswerChangedListener onAnswerChangedListener) { 494 | this.onAnswerChangedListener = onAnswerChangedListener; 495 | } 496 | 497 | 498 | 499 | public void setCheckedOption(int option) { 500 | for (int i = 0; i < checkBoxes.size(); i++) { 501 | if (i == option - 1) { 502 | checkBoxes.get(i).setChecked(true); 503 | break; 504 | } else { 505 | checkBoxes.get(i).setChecked(false); 506 | } 507 | } 508 | } 509 | 510 | public void setCheckedOption(String option) { 511 | for (CheckBox checkBox : checkBoxes) { 512 | if (checkBox.getText().equals(option)) { 513 | checkBox.setChecked(true); 514 | break; 515 | } else { 516 | checkBox.setChecked(false); 517 | } 518 | } 519 | } 520 | 521 | public void setOptionText(int index, String text){ 522 | checkBoxes.get(index).setText(text); 523 | } 524 | 525 | public CheckBox getCheckbox(int index){ 526 | return checkBoxes.get(index); 527 | } 528 | 529 | public TextView getQuestionTitleTextView(){ 530 | return findViewById(R.id.question_title); 531 | } 532 | 533 | public TextView getQuestionNumberTextView(){ 534 | return findViewById(R.id.question_number); 535 | } 536 | 537 | public int getCorrectAnswer(){ 538 | return correctAnswer; 539 | } 540 | 541 | public boolean isAnswerCorrect() throws Exception{ 542 | if (getCorrectAnswer() == Question.NO_ANSWER){ 543 | throw new Exception("There is no correct answer for this question."); 544 | } 545 | return getCorrectAnswer() == getSelectedAnswer(); 546 | } 547 | 548 | public String[] getOptions(){ 549 | return allOptions; 550 | } 551 | 552 | public void setCorrectAnswer(int correctAnswer){ 553 | this.correctAnswer = correctAnswer; 554 | } 555 | } 556 | -------------------------------------------------------------------------------- /CheckboxQuestion/CheckboxQuestion/src/main/java/com/aadyad/checkboxquestion/Views/YesOrNoQuestion.java: -------------------------------------------------------------------------------- 1 | package com.aadyad.checkboxquestion.Views; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.util.Log; 7 | import android.view.Gravity; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.CheckBox; 12 | import android.widget.LinearLayout; 13 | import android.widget.TextView; 14 | 15 | import androidx.annotation.Nullable; 16 | 17 | import com.aadyad.checkboxquestion.OnAnswerChangedListener; 18 | import com.aadyad.checkboxquestion.Question; 19 | import com.aadyad.checkboxquestion.QuestionListSettings; 20 | import com.aadyad.checkboxquestion.R; 21 | 22 | public class YesOrNoQuestion extends LinearLayout { 23 | 24 | public static final int LEFT = 0; 25 | public static final int CENTER = 1; 26 | public static final int RIGHT = 2; 27 | 28 | OnAnswerChangedListener onAnswerChangedListener; 29 | 30 | private LinearLayout layout; 31 | private int spacing; 32 | private int correctAnswer; 33 | 34 | private int buttonClicked = 0; //0 is not clicked, 1 is no, 2 is yes 35 | 36 | public YesOrNoQuestion(Context context) { 37 | this(context, null); 38 | this.onAnswerChangedListener = null; 39 | } 40 | 41 | public YesOrNoQuestion(Context context, @Nullable AttributeSet attrs) { 42 | super(context, attrs); 43 | setOrientation(LinearLayout.VERTICAL); 44 | LayoutInflater.from(context).inflate(R.layout.yes_or_no_question, this, true); 45 | this.onAnswerChangedListener = null; 46 | 47 | String title; 48 | String number; 49 | int spacing; 50 | int boxLocation; 51 | int tempCorrectAnswer; 52 | int orientation; 53 | float questionTextSize; 54 | float checkBoxTextSize; 55 | boolean numberEnabled; 56 | TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.YesOrNoQuestion, 0, 0); 57 | 58 | try { 59 | //optionLayoutHeight = a.getFloat(R.styleable.YesOrNoQuestion_option_layout_height, QuestionListSettings.TEXT_SIZE_DEFAULT); 60 | questionTextSize = a.getFloat(R.styleable.YesOrNoQuestion_question_text_size, QuestionListSettings.TEXT_SIZE_DEFAULT); 61 | checkBoxTextSize = a.getFloat(R.styleable.YesOrNoQuestion_option_text_size, QuestionListSettings.TEXT_SIZE_DEFAULT); 62 | //questionLayoutHeight = a.getFloat(R.styleable.YesOrNoQuestion_question_layout_height, QuestionListSettings.TEXT_SIZE_DEFAULT); 63 | title = a.getString(R.styleable.YesOrNoQuestion_question_title); 64 | tempCorrectAnswer = a.getInt(R.styleable.YesOrNoQuestion_correct_answer, 0); 65 | boxLocation = a.getInt(R.styleable.YesOrNoQuestion_checkbox_location, 0); 66 | orientation = a.getInt(R.styleable.YesOrNoQuestion_checkbox_orientation, 0); 67 | spacing = a.getInt(R.styleable.YesOrNoQuestion_spacing_between_boxes, 17); 68 | number = a.getString(R.styleable.YesOrNoQuestion_question_number); 69 | numberEnabled = a.getBoolean(R.styleable.YesOrNoQuestion_number_enabled, true); 70 | } finally { 71 | a.recycle(); 72 | } 73 | 74 | init(title, number, numberEnabled, spacing, orientation, boxLocation, questionTextSize, checkBoxTextSize, correctAnswer); 75 | } 76 | 77 | // Setup views 78 | public void init(String title, String number, boolean numEnabled, int spacing, int orientation, int boxLocation, float questionSize, float checkBoxSize, int correctAnswer) { 79 | TextView questionNumber = (TextView) findViewById(R.id.question_number); 80 | layout = findViewById(R.id.checkBoxHolder); 81 | 82 | this.spacing = spacing; 83 | this.correctAnswer = correctAnswer; 84 | 85 | //Todo: Set height if size == auto. 86 | //Todo: Also use height 87 | 88 | setQuestionTextSize(questionSize); 89 | setOptionTextSize(checkBoxSize); 90 | 91 | if (boxLocation == LEFT){ 92 | layout.setGravity(Gravity.LEFT); 93 | } else if (boxLocation == CENTER){ 94 | layout.setGravity(Gravity.CENTER); 95 | } else if (boxLocation == RIGHT){ 96 | layout.setGravity(Gravity.RIGHT); 97 | } 98 | 99 | setQuestion(title); 100 | if (numEnabled){ 101 | setQuestionNumber(number); 102 | questionNumber.setVisibility(VISIBLE); 103 | } else{ 104 | questionNumber.setVisibility(GONE); 105 | } 106 | 107 | setCheckboxOrientation(orientation); 108 | 109 | onFinishInflate(); 110 | } 111 | 112 | @Override 113 | protected void onFinishInflate() { 114 | super.onFinishInflate(); 115 | final CheckBox yes = (CheckBox) findViewById(R.id.yes); 116 | final CheckBox no = (CheckBox) findViewById(R.id.no); 117 | 118 | yes.setOnClickListener(new OnClickListener() { 119 | @Override 120 | public void onClick(View v) { 121 | no.setChecked(false); 122 | yes.setChecked(true); 123 | buttonClicked = 1; 124 | if (onAnswerChangedListener != null) { 125 | onAnswerChangedListener.onAnswerChanged(buttonClicked, yes.getText().toString()); 126 | } 127 | } 128 | }); 129 | 130 | no.setOnClickListener(new OnClickListener() { 131 | @Override 132 | public void onClick(View v) { 133 | no.setChecked(true); 134 | yes.setChecked(false); 135 | buttonClicked = 2; 136 | if (onAnswerChangedListener != null) { 137 | onAnswerChangedListener.onAnswerChanged(buttonClicked, no.getText().toString()); 138 | } 139 | } 140 | }); 141 | } 142 | 143 | public int getSelectedAnswer(){ 144 | return buttonClicked; 145 | } 146 | 147 | public void setQuestion(String question){ 148 | TextView questionTitle = (TextView) findViewById(R.id.question_title); 149 | questionTitle.setText(question); 150 | } 151 | 152 | public void setOptionTextSize(float optionTextSize){ 153 | final CheckBox yes = (CheckBox) findViewById(R.id.yes); 154 | final CheckBox no = (CheckBox) findViewById(R.id.no); 155 | 156 | if (optionTextSize == QuestionListSettings.TEXT_SIZE_AUTO){ 157 | //Todo: add code to auto adjust size using textheight 158 | }else if (!(optionTextSize == QuestionListSettings.TEXT_SIZE_DEFAULT)){ 159 | yes.setTextSize(optionTextSize); 160 | no.setTextSize(optionTextSize); 161 | } 162 | } 163 | 164 | public void setQuestionTextSize(float questionTextSize){ 165 | TextView questionNumber = (TextView) findViewById(R.id.question_number); 166 | TextView questionTitle = (TextView) findViewById(R.id.question_title); 167 | 168 | if (questionTextSize == QuestionListSettings.TEXT_SIZE_AUTO){ 169 | //Todo: add code to auto adjust size using height 170 | } else if (!(questionTextSize == QuestionListSettings.TEXT_SIZE_DEFAULT)){ 171 | questionTitle.setTextSize(questionTextSize); 172 | questionNumber.setTextSize(questionTextSize); 173 | } 174 | } 175 | 176 | public void setQuestionNumber(String number){ 177 | TextView questionNumber = (TextView) findViewById(R.id.question_number); 178 | questionNumber.setText(number + ". "); 179 | } 180 | 181 | public void setCheckboxOrientation(int orientation){ 182 | 183 | View space = findViewById(R.id.spacing); 184 | 185 | ViewGroup.LayoutParams layoutParams = space.getLayoutParams(); 186 | 187 | if (orientation == Question.HORIZONTAL){ 188 | layoutParams.width = spacing; 189 | layoutParams.height = 0; 190 | space.setLayoutParams(layoutParams); 191 | layout.setOrientation(HORIZONTAL); 192 | } else if (orientation == Question.VERTICAL || orientation == Question.FULL_VERTICAL){ 193 | layout.setOrientation(VERTICAL); 194 | layoutParams.height = spacing; 195 | layoutParams.width = 0; 196 | space.setLayoutParams(layoutParams); 197 | } 198 | } 199 | 200 | public void addOnAnswerChangedListener(OnAnswerChangedListener onAnswerChangedListener) { 201 | this.onAnswerChangedListener = onAnswerChangedListener; 202 | } 203 | 204 | public void setCheckedOption(int option){ 205 | final CheckBox yes = (CheckBox) findViewById(R.id.yes); 206 | final CheckBox no = (CheckBox) findViewById(R.id.no); 207 | if (option == 1){ 208 | yes.setChecked(true); 209 | no.setChecked(false); 210 | } else if (option == 2){ 211 | yes.setChecked(false); 212 | no.setChecked(true); 213 | } 214 | } 215 | 216 | public void setCheckedOption(String option){ 217 | final CheckBox yes = (CheckBox) findViewById(R.id.yes); 218 | final CheckBox no = (CheckBox) findViewById(R.id.no); 219 | if (option.equals("Yes")){ 220 | yes.setChecked(true); 221 | no.setChecked(false); 222 | } else if (option.equals("No")){ 223 | yes.setChecked(false); 224 | no.setChecked(true); 225 | } 226 | } 227 | 228 | public TextView getQuestionTitleTextView(){ 229 | return findViewById(R.id.question_title); 230 | } 231 | 232 | public TextView getQuestionNumberTextView(){ 233 | return findViewById(R.id.question_number); 234 | } 235 | 236 | public int getCorrectAnswer(){ 237 | return correctAnswer; 238 | } 239 | 240 | public boolean isAnswerCorrect() throws Exception{ 241 | if (getCorrectAnswer() == Question.NO_ANSWER){ 242 | throw new Exception("There is no correct answer for this question."); 243 | } 244 | return getCorrectAnswer() == getSelectedAnswer(); 245 | } 246 | 247 | public void setCorrectAnswer(int correctAnswer){ 248 | this.correctAnswer = correctAnswer; 249 | } 250 | } -------------------------------------------------------------------------------- /CheckboxQuestion/CheckboxQuestion/src/main/res/layout/multiple_answer_question.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 18 | 19 | 24 | 25 | 26 | 27 | 32 | 33 | 38 | 39 | 44 | 45 | 49 | 50 | 55 | 56 | 57 | 61 | 62 | 67 | 68 | 73 | 74 | 78 | 79 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /CheckboxQuestion/CheckboxQuestion/src/main/res/layout/multiple_choice_question.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 18 | 19 | 24 | 25 | 26 | 27 | 32 | 33 | 38 | 39 | 44 | 45 | 49 | 50 | 55 | 56 | 57 | 61 | 62 | 67 | 68 | 73 | 74 | 78 | 79 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /CheckboxQuestion/CheckboxQuestion/src/main/res/layout/yes_or_no_question.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 10 | 11 | 16 | 17 | 22 | 23 | 24 | 25 | 30 | 31 | 36 | 37 | 41 | 42 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /CheckboxQuestion/CheckboxQuestion/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /CheckboxQuestion/CheckboxQuestion/src/test/java/com/aadyad/checkboxquestion/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.aadyad.checkboxquestion; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /CheckboxQuestion/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /CheckboxQuestion/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 30 5 | buildToolsVersion "30.0.3" 6 | 7 | defaultConfig { 8 | applicationId "com.aadyad.checkboxquestions_library" 9 | minSdkVersion 16 10 | targetSdkVersion 30 11 | versionCode 1 12 | versionName "1.0" 13 | multiDexEnabled true 14 | 15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 16 | } 17 | 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | } 25 | 26 | dependencies { 27 | implementation 'com.google.code.gson:gson:2.8.6' 28 | implementation 'org.jsoup:jsoup:1.13.1' 29 | implementation 'com.android.support:multidex:1.0.3' //enter the latest version 30 | implementation fileTree(dir: "libs", include: ["*.jar"]) 31 | implementation 'androidx.appcompat:appcompat:1.2.0' 32 | implementation("com.squareup.okhttp3:okhttp:3.9.1") 33 | implementation project(path: ':CheckboxQuestion') 34 | implementation 'androidx.constraintlayout:constraintlayout:2.0.4' 35 | implementation 'org.jetbrains:annotations-java5:15.0' 36 | testImplementation 'junit:junit:4.12' 37 | androidTestImplementation 'androidx.test.ext:junit:1.1.2' 38 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 39 | 40 | } -------------------------------------------------------------------------------- /CheckboxQuestion/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /CheckboxQuestion/app/src/androidTest/java/com/aadyad/checkboxquestions_library/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.aadyad.checkboxquestions_library; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("com.aadyad.librarycreate", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /CheckboxQuestion/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /CheckboxQuestion/app/src/main/java/com/aadyad/checkboxquestions_library/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.aadyad.checkboxquestions_library; 2 | 3 | import android.os.Bundle; 4 | import android.util.Log; 5 | import android.view.View; 6 | import android.widget.LinearLayout; 7 | import android.widget.Toast; 8 | 9 | import androidx.appcompat.app.AppCompatActivity; 10 | 11 | import com.aadyad.checkboxquestion.OnAnswerChangedListener; 12 | import com.aadyad.checkboxquestion.Question; 13 | import com.aadyad.checkboxquestion.QuestionList; 14 | import com.aadyad.checkboxquestion.QuestionListSettings; 15 | import com.aadyad.checkboxquestion.Views.MultipleAnswerQuestion; 16 | import com.aadyad.checkboxquestion.Views.MultipleChoiceQuestion; 17 | 18 | import org.json.JSONArray; 19 | import org.json.JSONException; 20 | import org.json.JSONObject; 21 | import org.jsoup.Jsoup; 22 | 23 | import java.io.IOException; 24 | import java.util.ArrayList; 25 | import java.util.Arrays; 26 | import java.util.Collections; 27 | 28 | import okhttp3.Call; 29 | import okhttp3.Callback; 30 | import okhttp3.OkHttpClient; 31 | import okhttp3.Request; 32 | import okhttp3.Response; 33 | 34 | public class MainActivity extends AppCompatActivity { 35 | 36 | QuestionList questionList; 37 | JSONObject jsonObject; 38 | OkHttpClient client; 39 | String jsonData; 40 | ArrayList list; 41 | 42 | @Override 43 | protected void onCreate(Bundle savedInstanceState) { 44 | super.onCreate(savedInstanceState); 45 | setContentView(R.layout.activity_main); 46 | 47 | final LinearLayout linearLayout = findViewById(R.id.questionLayout); 48 | 49 | client = new OkHttpClient(); 50 | 51 | Request request = new Request.Builder() 52 | .url("https://opentdb.com/api.php?amount=20&category=9&difficulty=medium&type=multiple") 53 | .build(); 54 | 55 | Call call = client.newCall(request); 56 | call.enqueue(new Callback() { 57 | 58 | public void onResponse(Call call, Response response) throws IOException { 59 | jsonData = response.body().string(); 60 | Log.d("json", "onResponse: " + jsonData); 61 | try { 62 | jsonObject = new JSONObject(jsonData); 63 | } catch (JSONException e) { 64 | e.printStackTrace(); 65 | } 66 | 67 | JSONArray array = null; 68 | try { 69 | array = jsonObject.getJSONArray("results"); 70 | } catch (JSONException e) { 71 | e.printStackTrace(); 72 | } 73 | 74 | list = new ArrayList<>(); 75 | for (int i = 0; i < array.length(); i++) { 76 | JSONObject obj; 77 | String question = null; 78 | String[] answers = null; 79 | String correctAnswer = null; 80 | try { 81 | obj = (JSONObject) array.get(i); 82 | question = Jsoup.parse(obj.getString("question")).text(); 83 | correctAnswer = Jsoup.parse(obj.getString("correct_answer")).text(); 84 | JSONArray jsonArray = obj.getJSONArray("incorrect_answers"); 85 | answers = new String[]{Jsoup.parse((String) jsonArray.get(0)).text(), Jsoup.parse((String) jsonArray.get(1)).text(), Jsoup.parse((String) jsonArray.get(2)).text(), Jsoup.parse(correctAnswer).text()}; 86 | Collections.shuffle(Arrays.asList(answers)); 87 | Log.d("TAG", "shuffled: " + Arrays.toString(answers)); 88 | } catch (JSONException e) { 89 | e.printStackTrace(); 90 | } 91 | list.add(new Question(question, correctAnswer, Question.MULTIPLE_CHOICE_QUESTION, answers)); 92 | } 93 | 94 | MainActivity.this.runOnUiThread(new Runnable() { 95 | @Override 96 | public void run() { 97 | QuestionListSettings questionListSettings = new QuestionListSettings.SettingsBuilder() 98 | .setCheckboxLocation(Question.LEFT) 99 | .setCheckBoxOrientation(Question.FULL_VERTICAL) 100 | .setNumberEnabled(true) 101 | .setOptionTextSize(QuestionListSettings.TEXT_SIZE_DEFAULT) 102 | .setQuestionTextSize(QuestionListSettings.TEXT_SIZE_DEFAULT) 103 | .setSpacing(15) 104 | .create(); 105 | 106 | list.add(new Question("Hi", new ArrayList(Arrays.asList(1, 2, 3)), Question.MULTIPLE_ANSWER_QUESTION, "sa", "adasda", "adasd", "sdasd", "sahusaudsia")); 107 | list.add(new Question("Yeet?", Question.NO_ANSWER, Question.YES_OR_NO_QUESTION)); 108 | 109 | questionList = new QuestionList(list, questionListSettings, getApplicationContext()); 110 | questionList.createQuestionViews(); 111 | 112 | for (int i = 0; i < questionList.getQuestionViews().getChildCount(); i++){ 113 | final int finalI = i; 114 | final int finalI1 = i; 115 | questionList.addOnAnswerChangedListener(i, new OnAnswerChangedListener() { 116 | @Override 117 | public void onAnswerChanged(int selectedAnswerIndex, String selectedAnswerText) { 118 | try { 119 | Toast.makeText(MainActivity.this, "" + ((MultipleChoiceQuestion) questionList.getQuestion(finalI1)).isAnswerCorrect(), Toast.LENGTH_SHORT).show(); 120 | } catch (Exception e) { 121 | e.printStackTrace(); 122 | } 123 | } 124 | 125 | @Override 126 | public void onAnswerChanged(ArrayList listOfSelectedAnswerIndexes) { 127 | try { 128 | Toast.makeText(MainActivity.this, "" + ((MultipleAnswerQuestion) questionList.getQuestion(finalI1)).isAnswerCorrect(), Toast.LENGTH_SHORT).show(); 129 | } catch (Exception e) { 130 | e.printStackTrace(); 131 | } 132 | } 133 | }); 134 | } 135 | 136 | linearLayout.addView(questionList.getQuestionViews()); 137 | } 138 | }); 139 | } 140 | 141 | public void onFailure(Call call, IOException e) { 142 | Log.e("Error", "onFailure: ", e); 143 | } 144 | }); 145 | } 146 | 147 | public void logAnswers(View v) { 148 | Log.d("Questions answered", "logAnswers: " + questionList.areAllQuestionsAnswered()); 149 | Log.d("Questions answered", "percentage: " + questionList.getPercentageOfCorrectAnswers()); 150 | String s = ""; 151 | for (Object i : questionList.getSelectedAnswers()) { 152 | try { 153 | s += (int) i; 154 | } catch (Exception ignored) { 155 | } 156 | try { 157 | s += (ArrayList) i; 158 | } catch (Exception ignored) { 159 | } 160 | } 161 | 162 | Log.d("answers", "logAnswers: " + s); 163 | } 164 | } -------------------------------------------------------------------------------- /CheckboxQuestion/app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /CheckboxQuestion/app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /CheckboxQuestion/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 |