Better(?) navigation

This commit is contained in:
MrLetsplay 2023-06-18 22:05:38 +02:00
parent 4c2558f848
commit d1c774b496
Signed by: mr
SSH Key Fingerprint: SHA256:92jBH80vpXyaZHjaIl47pjRq+Yt7XGTArqQg1V7hSqg
15 changed files with 250 additions and 56 deletions

View File

@ -7,11 +7,11 @@
<deviceKey> <deviceKey>
<Key> <Key>
<type value="SERIAL_NUMBER" /> <type value="SERIAL_NUMBER" />
<value value="R38N50464FV" /> <value value="9eb4b614" />
</Key> </Key>
</deviceKey> </deviceKey>
</Target> </Target>
</runningDeviceTargetSelectedWithDropDown> </runningDeviceTargetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2023-06-17T15:52:55.310628363Z" /> <timeTargetWasSelectedWithDropDown value="2023-06-18T17:04:59.896380543Z" />
</component> </component>
</project> </project>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings"> <component name="GradleSettings">
<option name="linkedExternalProjectsSettings"> <option name="linkedExternalProjectsSettings">
<GradleProjectSettings> <GradleProjectSettings>

View File

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" /> <component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="jbr-17" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">

View File

@ -9,6 +9,9 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.NavOptions;
import androidx.navigation.Navigation;
import com.cringe_studios.cringe_authenticator.databinding.FragmentDynamicBinding; import com.cringe_studios.cringe_authenticator.databinding.FragmentDynamicBinding;
import com.cringe_studios.cringe_authenticator.databinding.FragmentFirstBinding; import com.cringe_studios.cringe_authenticator.databinding.FragmentFirstBinding;
@ -28,6 +31,10 @@ public class DynamicFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = FragmentDynamicBinding.inflate(inflater, container, false); binding = FragmentDynamicBinding.inflate(inflater, container, false);
binding.buttonSecond.setText(requireArguments().getString("sus")); binding.buttonSecond.setText(requireArguments().getString("sus"));
binding.buttonSecond.setOnClickListener(view -> {
NavigationUtil.navigate(this, SecondFragment.class, null);
});
return binding.getRoot(); return binding.getRoot();
} }
} }

View File

@ -9,9 +9,13 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.biometric.BiometricPrompt; import androidx.biometric.BiometricPrompt;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.NavOptions;
import androidx.navigation.Navigation;
import androidx.navigation.fragment.NavHostFragment; import androidx.navigation.fragment.NavHostFragment;
import com.cringe_studios.cringe_authenticator.databinding.FragmentFirstBinding; import com.cringe_studios.cringe_authenticator.databinding.FragmentFirstBinding;
@ -36,41 +40,13 @@ public class FirstFragment extends Fragment {
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
binding.buttonFirst.setOnClickListener(new View.OnClickListener() { binding.buttonFirst.setOnClickListener(view1 -> {
@Override
public void onClick(View view) {
/*NavHostFragment.findNavController(FirstFragment.this) /*NavHostFragment.findNavController(FirstFragment.this)
.navigate(R.id.action_FirstFragment_to_SecondFragment);*/ .navigate(R.id.action_FirstFragment_to_SecondFragment);*/
Executor executor = ContextCompat.getMainExecutor(FirstFragment.this.getContext());
BiometricPrompt prompt = new BiometricPrompt(FirstFragment.this, executor, new BiometricPrompt.AuthenticationCallback() {
@Override
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
}
@Override
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
Bundle b = new Bundle(); Bundle b = new Bundle();
b.putString("sus", "Impostor"); b.putString("sus", "Impostor");
NavigationUtil.navigate(this, DynamicFragment.class, b);
getParentFragment().getChildFragmentManager().beginTransaction()
.setReorderingAllowed(true)
.replace(R.id.nav_host_fragment_content_main, DynamicFragment.class, b)
.addToBackStack(null)
.commit();
}
});
BiometricPrompt.PromptInfo info = new BiometricPrompt.PromptInfo.Builder()
.setTitle("Biometric login for my app")
.setSubtitle("Log in using your biometric credential")
.setAllowedAuthenticators(BIOMETRIC_STRONG | DEVICE_CREDENTIAL)
.build();
prompt.authenticate(info);
}
}); });
} }

View File

@ -1,13 +1,19 @@
package com.cringe_studios.cringe_authenticator; package com.cringe_studios.cringe_authenticator;
import static androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRONG;
import static androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL;
import android.os.Bundle; import android.os.Bundle;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import android.view.View; import android.view.View;
import androidx.biometric.BiometricPrompt;
import androidx.core.content.ContextCompat;
import androidx.core.view.WindowCompat; import androidx.core.view.WindowCompat;
import androidx.navigation.NavController; import androidx.navigation.NavController;
import androidx.navigation.Navigation; import androidx.navigation.Navigation;
@ -19,6 +25,8 @@ import com.cringe_studios.cringe_authenticator.databinding.ActivityMainBinding;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import java.util.concurrent.Executor;
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
private AppBarConfiguration appBarConfiguration; private AppBarConfiguration appBarConfiguration;
@ -28,6 +36,31 @@ public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Executor executor = ContextCompat.getMainExecutor(this);
BiometricPrompt prompt = new BiometricPrompt(this, executor, new BiometricPrompt.AuthenticationCallback() {
@Override
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
finishAffinity();
}
@Override
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
launchApp();
}
});
/*BiometricPrompt.PromptInfo info = new BiometricPrompt.PromptInfo.Builder()
.setTitle("Biometric login for my app")
.setSubtitle("Log in using your biometric credential")
.setAllowedAuthenticators(BIOMETRIC_STRONG | DEVICE_CREDENTIAL)
.build();
prompt.authenticate(info);*/
launchApp();
}
private void launchApp() {
binding = ActivityMainBinding.inflate(getLayoutInflater()); binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot()); setContentView(binding.getRoot());
@ -37,14 +70,9 @@ public class MainActivity extends AppCompatActivity {
appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build(); appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration); NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
binding.fab.setOnClickListener(new View.OnClickListener() { binding.fab.setOnClickListener(view -> Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAnchorView(R.id.fab) .setAnchorView(R.id.fab)
.setAction("Action", null).show(); .setAction("Action", null).show());
}
});
} }
@Override @Override
@ -75,4 +103,9 @@ public class MainActivity extends AppCompatActivity {
return NavigationUI.navigateUp(navController, appBarConfiguration) return NavigationUI.navigateUp(navController, appBarConfiguration)
|| super.onSupportNavigateUp(); || super.onSupportNavigateUp();
} }
public void openSettings(MenuItem item) {
NavigationUtil.navigate(this, SettingsFragment.class, null);
}
} }

View File

@ -0,0 +1,25 @@
package com.cringe_studios.cringe_authenticator;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.cringe_studios.cringe_authenticator.databinding.FragmentMenuBinding;
public class MenuFragment extends Fragment {
private FragmentMenuBinding binding;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = FragmentMenuBinding.inflate(inflater);
return binding.getRoot();
}
}

View File

@ -0,0 +1,27 @@
package com.cringe_studios.cringe_authenticator;
import android.app.Activity;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
public class NavigationUtil {
public static void navigate(AppCompatActivity activity, Class<? extends Fragment> fragmentClass, Bundle args) {
navigate(activity.getSupportFragmentManager().getPrimaryNavigationFragment().getChildFragmentManager(), fragmentClass, args);
}
public static void navigate(Fragment currentFragment, Class<? extends Fragment> fragmentClass, Bundle args) {
navigate(currentFragment.getParentFragment().getChildFragmentManager(), fragmentClass, args);
}
private static void navigate(FragmentManager manager, Class<? extends Fragment> fragmentClass, Bundle args) {
manager.beginTransaction()
.setReorderingAllowed(true)
.replace(R.id.nav_host_fragment_content_main, fragmentClass, args)
.commit();
}
}

View File

@ -31,8 +31,7 @@ public class SecondFragment extends Fragment {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
binding.buttonSecond.setOnClickListener(view1 -> { binding.buttonSecond.setOnClickListener(view1 -> {
NavHostFragment.findNavController(SecondFragment.this) NavigationUtil.navigate(this, FirstFragment.class, null);
.navigate(R.id.action_SecondFragment_to_FirstFragment);
}); });
} }

View File

@ -0,0 +1,34 @@
package com.cringe_studios.cringe_authenticator;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import com.cringe_studios.cringe_authenticator.databinding.FragmentSettingsBinding;
public class SettingsFragment extends Fragment {
private FragmentSettingsBinding binding;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = FragmentSettingsBinding.inflate(inflater);
binding.switch1.setOnCheckedChangeListener((view, checked) -> {
NavController controller = Navigation.findNavController(binding.getRoot());
controller.navigate(R.id.FirstFragment);
});
return binding.getRoot();
}
}

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<stroke
android:width="0dp"
android:color="#FFFFFF" />
<gradient
android:angle="180"
android:endColor="?attr/colorPrimary"
android:startColor="?attr/colorSecondary" />
<corners
android:bottomLeftRadius="20dp"
android:bottomRightRadius="20dp"
android:topLeftRadius="20dp"
android:topRightRadius="20dp" />
</shape>
</item>
<item
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp">
<shape>
<stroke
android:width="0dp"
android:color="#FFFFFF" />
<gradient
android:angle="180"
android:endColor="?attr/colorOnBackground"
android:startColor="?attr/colorOnBackground" />
<corners
android:bottomLeftRadius="20dp"
android:bottomRightRadius="20dp"
android:topLeftRadius="20dp"
android:topRightRadius="20dp" />
</shape>
</item>
</layer-list>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FirstFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/round_rectangle"
android:text="Button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FirstFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<Switch
android:id="@+id/switch1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Enable something"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:layout_editor_absoluteY="16dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

View File

@ -6,5 +6,6 @@
android:id="@+id/action_settings" android:id="@+id/action_settings"
android:orderInCategory="100" android:orderInCategory="100"
android:title="@string/action_settings" android:title="@string/action_settings"
app:showAsAction="never" /> app:showAsAction="never"
android:onClick="openSettings" />
</menu> </menu>

View File

@ -10,19 +10,23 @@
android:name="com.cringe_studios.cringe_authenticator.FirstFragment" android:name="com.cringe_studios.cringe_authenticator.FirstFragment"
android:label="@string/first_fragment_label" android:label="@string/first_fragment_label"
tools:layout="@layout/fragment_first"> tools:layout="@layout/fragment_first">
<action
android:id="@+id/action_FirstFragment_to_SecondFragment"
app:destination="@id/SecondFragment" />
</fragment> </fragment>
<fragment <fragment
android:id="@+id/SecondFragment" android:id="@+id/SecondFragment"
android:name="com.cringe_studios.cringe_authenticator.SecondFragment" android:name="com.cringe_studios.cringe_authenticator.SecondFragment"
android:label="@string/second_fragment_label" android:label="@string/second_fragment_label"
tools:layout="@layout/fragment_second"> tools:layout="@layout/fragment_second">
</fragment>
<action <fragment
android:id="@+id/action_SecondFragment_to_FirstFragment" android:id="@+id/SettingsFragment"
app:destination="@id/FirstFragment" /> android:name="com.cringe_studios.cringe_authenticator.SettingsFragment"
android:label="Settings"
tools:layout="@layout/fragment_settings">
</fragment>
<fragment
android:id="@+id/DynamicFragment"
android:name="com.cringe_studios.cringe_authenticator.DynamicFragment"
android:label="Dynamic"
tools:layout="@layout/fragment_dynamic">
</fragment> </fragment>
</navigation> </navigation>