diff --git a/app/build.gradle b/app/build.gradle index fbbc57c..360e7c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,7 +5,7 @@ android { defaultConfig { applicationId "atorch.statspuzzles" - minSdkVersion 16 + minSdkVersion 19 targetSdkVersion 34 versionCode 32 versionName "4.0" @@ -35,6 +35,7 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.navigation:navigation-fragment:2.5.3' implementation 'androidx.navigation:navigation-ui:2.5.3' + implementation 'androidx.viewpager2:viewpager2:1.1.0' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' diff --git a/app/src/androidTest/java/atorch/statspuzzles/PuzzleSelectionTest.java b/app/src/androidTest/java/atorch/statspuzzles/PuzzleSelectionTest.java index 785f739..82adc28 100644 --- a/app/src/androidTest/java/atorch/statspuzzles/PuzzleSelectionTest.java +++ b/app/src/androidTest/java/atorch/statspuzzles/PuzzleSelectionTest.java @@ -8,6 +8,7 @@ import androidx.test.espresso.assertion.ViewAssertions; import androidx.test.espresso.matcher.ViewMatchers; import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.action.ViewActions.swipeLeft; import org.junit.Rule; import org.junit.Test; @@ -34,4 +35,15 @@ public void easyPuzzlesButton_loadsEasyPuzzles() { Espresso.onView(ViewMatchers.withText(context.getString(R.string.puzzle, 1))) .check(ViewAssertions.matches(ViewMatchers.isDisplayed())); } + + @Test + public void swipeHorizontally_showsNextPuzzle() { + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + Espresso.onView(ViewMatchers.withText(context.getString(R.string.button_level_1))).perform(click()); + Espresso.onView(ViewMatchers.withText(context.getString(R.string.puzzle, 1))) + .check(ViewAssertions.matches(ViewMatchers.isDisplayed())); + Espresso.onView(ViewMatchers.withId(R.id.pager)).perform(swipeLeft()); + Espresso.onView(ViewMatchers.withText(context.getString(R.string.puzzle, 2))) + .check(ViewAssertions.matches(ViewMatchers.isDisplayed())); + } } diff --git a/app/src/main/java/atorch/statspuzzles/SolvePuzzle.java b/app/src/main/java/atorch/statspuzzles/SolvePuzzle.java index 0bd6aa3..50b412c 100644 --- a/app/src/main/java/atorch/statspuzzles/SolvePuzzle.java +++ b/app/src/main/java/atorch/statspuzzles/SolvePuzzle.java @@ -21,14 +21,15 @@ import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.ShareActionProvider; import androidx.core.view.MenuItemCompat; import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentPagerAdapter; -import androidx.viewpager.widget.ViewPager; import org.mariuszgromada.math.mxparser.Expression; @@ -36,6 +37,10 @@ import java.math.RoundingMode; import java.util.Random; +import androidx.viewpager2.adapter.FragmentStateAdapter; +import androidx.viewpager2.widget.ViewPager2; + + public class SolvePuzzle extends AppCompatActivity { // Following example at https://developer.android.com/training/sharing/shareaction.html private ShareActionProvider mShareActionProvider; @@ -44,7 +49,8 @@ public class SolvePuzzle extends AppCompatActivity { public static final String LEVEL = "atorch.statspuzzles.LEVEL"; private static final int roundingScale = 4; - private ViewPager puzzlePager; // Displays puzzles one at a time + // Displays puzzles one at a time + private ViewPager2 puzzlePager; private int level; @@ -64,18 +70,14 @@ public void onCreate(Bundle savedInstanceState) { level = intent.getIntExtra(PuzzleSelection.LEVEL, 0); } - FragmentManager fragmentManager = getSupportFragmentManager(); - res = new Res(getResources()); puzzlePager = findViewById(R.id.pager); - puzzlePager.setAdapter(new AppSectionsPagerAdapter(fragmentManager, level, res)); + puzzlePager.setAdapter(new AppSectionsPagerAdapter(this, level, res)); - puzzlePager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { - @Override public void onPageScrollStateChanged(int arg0) { - } - @Override public void onPageScrolled(int arg0, float arg1, int arg2) { - } - @Override public void onPageSelected(int puzzleIndex) { + puzzlePager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { + @Override + public void onPageSelected(int puzzleIndex) { + super.onPageSelected(puzzleIndex); prepareSharePuzzle(res.getPuzzle(level, puzzleIndex)); } }); @@ -209,30 +211,31 @@ String getFirstCongratulation(int level) { } } - public static class AppSectionsPagerAdapter extends FragmentPagerAdapter { + public static class AppSectionsPagerAdapter extends FragmentStateAdapter { private final int level; private final Res res; - public AppSectionsPagerAdapter(FragmentManager fm, int level, Res res) { - super(fm); + public AppSectionsPagerAdapter(@NonNull FragmentActivity fa, int level, Res res) { + super(fa); this.level = level; this.res = res; } + @NonNull @Override - public Fragment getItem(int puzzleIndex) { + public Fragment createFragment(int puzzleIndex) { Fragment fragment = new SolvePuzzleFragment(); Bundle args = new Bundle(); args.putInt(LEVEL, level); args.putInt(PUZZLE_INDEX, puzzleIndex); - fragment.setArguments(args); return fragment; } + @Override - public int getCount() { + public int getItemCount() { return res.getPuzzleCount(level); } } @@ -241,8 +244,6 @@ public static class SolvePuzzleFragment extends Fragment { private int level; private int puzzleIndex; - private double correctAnswer; - private ViewPager mViewPager; private Res res; @Override @@ -277,8 +278,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa submitButton.setOnClickListener(this::onSubmit); String answer = res.getAnswer(level, puzzleIndex); - Expression correctAnswerExpression = new Expression(answer); - correctAnswer = correctAnswerExpression.calculate(); // This needs to always parse correctly! EditText user_answer = rootView.findViewById(R.id.user_answer); SharedPreferences preferences = getActivity().getSharedPreferences("atorch.statspuzzles.data", Context.MODE_PRIVATE); @@ -291,7 +290,9 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa user_answer.setText(answer); // Show approx equal for correct answer TextView answerApprox = rootView.findViewById(R.id.answerApprox); - BigDecimal bd = new BigDecimal(correctAnswer).setScale(roundingScale, RoundingMode.HALF_EVEN); + Expression correctAnswerExpression = new Expression(answer); + double correctAnswerValue = correctAnswerExpression.calculate(); + BigDecimal bd = new BigDecimal(correctAnswerValue).setScale(roundingScale, RoundingMode.HALF_EVEN); answerApprox.setText(getString(R.string.approximate_result, bd)); } @@ -395,7 +396,7 @@ public void openCongratulationsAlert(View view) { editor.commit(); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - mViewPager = view.getRootView().findViewById(R.id.pager); + ViewPager2 viewPager = view.getRootView().findViewById(R.id.pager); int nPuzzles = res.getPuzzleCount(level); boolean solvedAllPuzzles = puzzles_solved >= nPuzzles; @@ -408,7 +409,7 @@ public void openCongratulationsAlert(View view) { if (next_puzzleIndex >= nPuzzles) { next_puzzleIndex = 0; } - mViewPager.setCurrentItem(next_puzzleIndex); + viewPager.setCurrentItem(next_puzzleIndex); dialog.cancel(); } ); diff --git a/app/src/main/res/layout/activity_solve_puzzle.xml b/app/src/main/res/layout/activity_solve_puzzle.xml index 75dc9aa..bc52c22 100644 --- a/app/src/main/res/layout/activity_solve_puzzle.xml +++ b/app/src/main/res/layout/activity_solve_puzzle.xml @@ -1,8 +1,8 @@ - - \ No newline at end of file + \ No newline at end of file