Remember path used in intents to override onBackPressed - java

I am dealing with a certain problem in android and I struggle to find a viable solution.
The situation is as follows:-
I have 4 activities A,B,C and D and two possible paths :
Path 1 : A,B,C,D
Path 2 : A,B',D
B and B' refer to the same activity but with different views ( a recyclerview is used in here ) depending on the activity I am initially ie B or A.
What I want to do is basically follow the paths like that : A,B,C,D ( direct ) and D,C,B,A ( when back is constantly pressed ). The same with the second one : A, B', D ( direct ) and D,B',A ( when back is constantly pressed ).
I have a lot of problems when back is pressed so I know that I have to override onBackPressed. But how exactly can I figure out in which case I am ( path 1 or path 2 )?
Thanks for your help,

Try this in one.
// Add activity
public static void addActivities(String actName, Activity _activity) {
if (Config.screenStack == null)
Config.screenStack = new HashMap<String, Activity>();
if (_activity != null)
Config.screenStack.put(actName, _activity);
}
// Remove Activity
public static void removeActivity(String key) {
if (Config.screenStack != null && Config.screenStack.size() > 0) {
Activity _activity = Config.screenStack.get(key);
if (_activity != null) {
Config.screenStack.remove(key);
_activity.finish();
}
}
}
User add activities before setContentView to add into the stack.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addActivities("DemoActivity", DemoActivity.this)
setContentView(R.layout.activity_create_feed_post);
}
If you want to finish all activity when you exist from app you can see this code.

Related

Why does my setOnClickListener only apply to last element each loop pass?

Sorry if the code is a bit convoluted, I've been spamming things out trying to fix this for ages.
I create children within a layout and track the number in which they were added, then compare them so we know which sets belong to which exercises. On click of the arrow, the set information should collapse but only the last view of each exercise does.
fully loaded
clicking to hide
all buttons clicked to hide
fun listeners() {
for (i in childCount3) {
val imageButton: TextView = binding.parentLinearLayout.getChildAt(i).weightTxt
val fragment = EditSetFragment()
imageButton.setOnClickListener {
supportFragmentManager.beginTransaction().replace(R.id.parent_linear_layout, fragment).commit()
}
}
// childList = 10 | childList2 = [0,3,6,8] | childList3 = [1,2,4,5,7,9]
var testCount = 0
var testCount2 = 0
for (i in 0 until childCount2.size) {
var matches = ArrayList<Int>()
val imageButton: ImageButton = binding.parentLinearLayout.getChildAt(childCount2[i]).expandCard
Log.d("I ", i.toString())
for (k in 0 until childCount3.size) {
Log.d("k ", k.toString())
Log.d("CHECKER ", binding.parentLinearLayout.getChildAt(childCount2[i]).instanceTxtEx.text.toString() + binding.parentLinearLayout.getChildAt(childCount3[k]).instanceTxt.text).toString()
if(binding.parentLinearLayout.getChildAt(childCount2[i]).instanceTxtEx.text == binding.parentLinearLayout.getChildAt(childCount3[k]).instanceTxt.text) {
matches.add(childCount3[k])
Log.d("MATCH ", i.toString())
imageButton.setOnClickListener{
binding.parentLinearLayout.getChildAt(childCount3[k]).visibility = GONE
}
}
}
}
}
It's a little hard to follow what you're doing, but I think you're going over each item in childCount2, grabbing its expand button, then trying to add a click listener for each child that item has in childCount3?
The problem is you can only set one click listener on a View, so in your loop you're not adding multiple listeners which each hide a button, you're replacing the current listener each time. So it ends up only hiding the last item you set a listener for.
If you're adding these items to the layout programmatically, can't you just store a list of the children of each top-level item? That way you can just set the listener once for each button, and in it just reference your list of its children. Something like this:
val parentsAndChildren = mutableMapOf<View, MutableList<View>>()
// Add your top-level (childCount2) views here, mapped to an empty list
// As you add children (childCount3), grab their parent's list and add the child to it
fun setUpCollapseButtons() {
// iterate over all the parents and set a click listener on their buttons
parentsAndChildren.keys.forEach { parent ->
parent.expandCard.setOnClickListener {
// grab the current list of children for this parent, and do the thing
parentsAndChildren[parent].forEach { it.visibility = GONE }
// could also do { it.visibility = if (it.visibility == VISIBLE) GONE else VISIBLE } for a toggle
}
}
}
I'm not 100% sure how you're referencing things like expandCard when getChildAt just returns a View, but you can use findViewById on each parent when you're setting up the click listeners. Hopefully that gives you the idea - it's much easier to just keep track of the views themselves, instead of having to go digging for them (and doing text comparisons to match them)
If you still want to do it this way, here's how you can set one click listener on each:
// collect all the parent Views
val parents = childCount2.map { i -> binding.parentLinearLayout.getChildAt(i) }
parents.forEach { parent ->
// collect all its children
val children = childCount3.map { j -> binding.parentLinearLayout.getChildAt(j) }
.filter { child -> parent.instanceTxtEx.text == child.instanceTxtEx.text }
// add a single click listener to the parent, make it affect all the children
parent.expandCard.setOnClickListener {
children.forEach { it.visibility = GONE }
}
}
There are fancier ways to collect the parents and children, but hopefully that makes sense - you need to collect them all before you can set the click listener that affects them all

I have an arrayList outside of an onClick method that refers to the arrayList, but it is giving me errors

I have an arrayList outside of an onClick() method. I am referring to some elements in the arrayList in my onClick() class. But when I type the name of the ArrayList and the list, it highlights in red. Both of the classes are public though.
I have tried putting the code of the arryalist and the list randomization process, but the it re randomizes every time I click something.
The part that is giving me errors is in the first case in the switch case statement, where I try to get the first position in the allImages arraylist, and the first position in the imageList List. They are in the onclick class. The arrayList and List are outside of that class.
I cannot put the arrayList and List inside of the class, because that will re randomize every time I click something. (I am trying to make a matching game)
Here is the code:
public void Random() {
Integer[] allImages = { R.drawable.cheetah, R.drawable.cheetah, R.drawable.chick, R.drawable.chick, R.drawable.fox,
R.drawable.fox, R.drawable.giraffe, R.drawable.giraffe, R.drawable.owl,
R.drawable.owl, R.drawable.panda, R.drawable.panda, R.drawable.sheep, R.drawable.sheep, R.drawable.tiger,
R.drawable.tiger};
List<Integer> imageList = Arrays.asList(allImages);
Collections.shuffle(imageList);
imageList.toArray(allImages);
}
public void onClick(View v) {
final int id = v.getId();
if (maxCounter < 2) {
switch (id) {
case R.id.one:
one.setBackgroundResource(allImages[0]); THE ALL IMAGES PART HIGHLIGHTS IN RED
unmatchedImages[maxCounter] = R.id.one;
unmatchedImages[maxCounter++] = imageList.get(0); ALSO IMAGE LIST HIGHLIGHTS IN RED
break;
//After this, i have cases for each button
}
}
else {
one.setBackgroundResource(R.drawable.qmarks);
//After this, i have a setBackgroundResource for each button
}
}
Please help. Any help is greatly appreciated.
Is your Random() should be method or class?
Base on name, which starts from uppercase (Random) it look like class.
But you added public void before name, so it's method.
I think you can move your Random() method (!) content to your Activity. Are you planning to set in Fragment or Activity?
Steps to do:
1) Move your list as field in your Activity (or fragment - I don't know what you have)
2) Shuffle list in onCreate() (or in different place but before first usage)
// 0 - Use it in your class.
// This "MainActivity" is only for example - use your name!
public class MainActivity extends AppCompatActivity {
// 1 - List of items
List<Integer> allImages = {R.drawable.cheetah, R.drawable.cheetah, R.drawable.chick,
R.drawable.chick, R.drawable.fox, R.drawable.fox, R.drawable.giraffe,
R.drawable.giraffe, R.drawable.owl, R.drawable.owl, R.drawable.panda,
R.drawable.panda, R.drawable.sheep, R.drawable.sheep, R.drawable.tiger,
R.drawable.tiger};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 2 - Shuffle them
Collections.shuffle(imageList);
}
.
.
.
}
The problem I see is that yes Random is public but in the OnClick() method your are trying to access a property of Random without telling who is the parent.
So instead of just using allImages and imageList.get() use Random().allImages and Random().imageList.get() Hope this helps.

DialogFragment - show() method

I would like to see DialogFragment after pressing the button, I have two code snippets:
First:
if (view.equals(b1)) {
Fragment2 fr2 = new Fragment2();
fr2.show(manager, "addCity");
}
I don't understand why this tag is in the show () method, since it has no effect on program change.
Second:
Fragment fr = manager.findFragmentByTag("addCity");
if (view.equals(b1)) {
if (fr != null) {
manager.beginTransaction().remove(fr).commit();
}
Fragment2 fr2 = new Fragment2();
fr2.show(manager, "addCity");
}
In the second example, I don't understand what this line of code is for:
Fragment fr = manager.findFragmentByTag("addCity");
Since the reference variable fr will always be null because there is currently no fragment under the name of such a tag.
In addition, why does this condition appear, since just the previous change fr will always be null, so this if will never come true.
if (fr != null) {
manager.beginTransaction().remove(fr).commit();
}
When you use show(manager, "addCity"), then second parameter is the tag for the Fragment. By using findFragmentByTag() with the same tag, you're looking to see if the DialogFragment already exists and, if it does (fr != null), then remove it.
This is very defensive code, probably made in an attempt to avoid users very, very quickly double tapping the button. However, because it doesn't use showNow() (instead of show()), it actually doesn't do a good job at this because show() is asynchronous.
In general, you don't need this code at all - just call show() without any of the ceremony, using whatever tag you want (the tag only matters if you're later trying to use findFragmentByTag() to retrieve your DialogFragment after the fact).
But if you do want to be defensive and avoid even the extremely rare chance that the user opens up two dialogs, then you need to
1) Use showNow() instead of show() so that the FragmentManager is immediately updated, ensuring that findFragmentByTag() actually does return the Fragment in that case
2) Instead of removing and then calling show() again, just don't call show() if it already being shown - you're just doing extra work.
This would mean your code would look like
if (view.equals(b1)) {
Fragment existingDialog = manager.findFragmentByTag("addCity");
// Only add a new dialog if it isn't already present.
if (existingDialog == null) {
Fragment2 fr2 = new Fragment2();
fr2.showAll(manager, "addCity");
}
}

How can I put two different variables inside of a textview in recyclerview when it runs a second time?

I have one recyclierview adapter in my project. It loads two times and puts variables inside textview in activity. I want it to load different for the second time when it loads.
I just tried to make if clause for it. I wanted to make it will work else statement for first time adapter load. And I put "1" inside of i so, second time if i equals "1" it will work inside of if. But, when it loads the second time it is default value of i.
public class VoyageInformationAdapter extends RecyclerView.Adapter {
private String i;
if (i == "1"){
viewHolderBus.textV_from_city.setText(leg.getTo_city());
viewHolderBus.textV_to_city.setText(leg.getFrom_city());
}else{
viewHolderBus.textV_from_city.setText(leg.getFrom_city());
viewHolderBus.textV_to_city.setText(leg.getTo_city());
i = "1";
}}
How can I solve this problem?
This code would work for you
public class VoyageInformationAdapter extends RecyclerView.Adapter {
private String i;
if (i != null && i.equals("1")){
viewHolderBus.textV_from_city.setText(leg.getTo_city());
viewHolderBus.textV_to_city.setText(leg.getFrom_city());
}else{
viewHolderBus.textV_from_city.setText(leg.getFrom_city());
viewHolderBus.textV_to_city.setText(leg.getTo_city());
i = "1";
}}

Getting a value from a class extending activity in a plugin

When jumping from Activity to activity via Cordova, plugin, i want to be able to put additional information into a bundle and pass it along with the intent. I seem to have issues getting the current activity and then getting a value via
public int getCounter(){return counter;}
I have a Activity Definition which, onCreate will set counter to a value from the passed in bundle.
I have a Cordova plugin then which i am working with, which will carry out the intent to next activity.
Echo Class is a mediary which will jump between acticities based on html clicks.
//In the Class: public class Echo extends CordovaPlugin
private void launchSecondActivity(String data, CallbackContext cc){
Bundle b = new Bundle();
int tmp = ((SecondaryActivity)cordova.getActivity()).getCounter();
tmp++;
b.putInt("id", tmp);
Intent i = new Intent(cordova.getActivity().getApplicationContext(), SecondaryActivity.class);
i.putExtras(b);
cordova.getActivity().startActivity(i);
cc.success();
}
It seems that it causes a seg fault of sorts, when i am trying to assign counter to tmp, in the line:
int tmp = ((SecondaryActivity)cordova.getActivity()).getCounter();
Is there something i am doing wrong? I am trying to get the currently active activity, and then call a public function in that activity.
End Goal: I am trying to take an int, and keep passing it into intents, incremented. So that way, it will know how deep into the activity chain it is. I am working on nested state saving and curious as to the depth i am at, at any given time. The tmp being passed into the activity will be incremented each time, so it will maintain a depth.
Instead of creating a class with get counter, storing the int in the Bundle and passing it to the next activity would be far easier.
Example:
//send item to plugin.
int item = 0; // or whatever it is
Bundle b = new Bundle();
b.put("ident", item);
Intent i = new Intent();
i.putExtras();
//...
And then on the next activity.
public void onCreate(Bundle savedInstanceState)
{
int item = getIntent().getExtras().getInt("ident");
}
Then you can do with it what you will. The answer overall while the previous activity as the old number. What does that mean? It means that you can increment and do whatever you want with it when passing it to the next activity. It is copied, so you can incrememnet and store it recursively. Allowing you to even say something like:
if (item ==0){/*set new source for Activity*/}
else if(item == 1){/*set source 2*/}
//etc.

Categories

Resources