How to change ImageView in fragment from pop up window class? - java

I want to change the ImageView in my fragment's xml when I click on an Image from a pop up window class.
Pop Up class
public class MoodPopUp extends Activity {
ImageView a,b,c,d,e,f,g,h,i;
ImageView main;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mood_picker_popup);
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int width = displayMetrics.widthPixels;
int height = displayMetrics.heightPixels;
//Pop Up Window Size
getWindow().setLayout((int) (width*.8),(int)(height*.6));
//Set emoji images on mood imageview
//Main Mood Image View
main = (ImageView) findViewById(R.id.MainMoodimageview);
//Pop Up Picker on Click
a = (ImageView) findViewById(R.id.Aemoji);
a.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
main.setImageResource(R.drawable.smiling);
}
});
}
This is the imageview from another fragment I want to change upon click.
<ImageView
android:id="#+id/MainMoodimageview"
android:layout_width="187dp"
android:layout_height="163dp"
android:layout_marginTop="19dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/divider3"
android:src="#drawable/ic_baseline_emoji_emotions_24" />

Welcome to Stack Overflow, #Enzo.
There are a few ways to accomplish what you want.
A traditional way to accomplish this is to use an interface in a dialog fragment.
Some ideas are in this question and set of answers
Callback to a Fragment from a DialogFragment
Another solution would be to use a shared ViewModel. Your picker can set the Drawable and you can use it in your other activity.
https://developer.android.com/topic/libraries/architecture/viewmodel
https://developer.android.com/codelabs/kotlin-android-training-view-model#0
The important part if you go the ViewModel route is to make sure that your two activities or fragments, etc, share the same scope.
Another easy way to accomplish this is to use a Singleton or a Kotlin object. This works well if you only every want one instance that all will read and write to.
https://kotlinlang.org/docs/object-declarations.html#object-declarations

Related

Android: How to call a different layout for 2 devices (tablet and phone)

I have an app that I want to run on both a phone and a tablet. I have 2 separate layouts (landscape) for both which are essentially the same except for their dimensions.
My question is how do I make the MainActivity.java detect the device that I'm running on and accordingly fire the activity based on the device being used.
I have looked into fragments but I couldn't really understand how to create them nevermind how to use them.
This is my MainActivity.java:
public class MainActivity extends AppCompatActivity {
EditText name;
ImageView oneStar, twoStar, threeStar, fourStar, fiveStar;
Intent intent;
FirebaseDatabase rootNode;
DatabaseReference reference;
public void displayScore() {
intent = new Intent(getApplicationContext(), Score.class);
startActivity(intent);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); //will hide the title
getSupportActionBar().hide(); // hide the title bar
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN); //enable full screen
setContentView(R.layout.activity_main);
final FirebaseAnalytics mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);
name = findViewById(R.id.editTextTextPersonName);
oneStar = findViewById(R.id.imageView1);
twoStar = findViewById(R.id.imageView2);
threeStar = findViewById(R.id.imageView3);
fourStar = findViewById(R.id.imageView4);
fiveStar = findViewById(R.id.imageView5);
oneStar.setTag(1);
twoStar.setTag(2);
threeStar.setTag(3);
fourStar.setTag(4);
fiveStar.setTag(5);
class OnClickListener implements View.OnClickListener {
#Override
public void onClick(View view) {
Bundle bundle = new Bundle();
bundle.putString(FirebaseAnalytics.Param.VALUE, view.getTag().toString());
if (name.length() == 0){
name.setError("Please enter your full name.");
}
else {
name.setError(null);
rootNode = FirebaseDatabase.getInstance();
reference = rootNode.getReference().child("Users");
//Fetch all values
String username = name.getText().toString();
String value = view.getTag().toString();
int rating = Integer.parseInt(value);
UserHelper helper = new UserHelper(username,rating);
reference.push().setValue(helper);
Toast.makeText(MainActivity.this, "Feedback submitted successfully!", Toast.LENGTH_SHORT).show();
sleep(2500);
displayScore();
}
}
}
oneStar.setOnClickListener(new OnClickListener ());
twoStar.setOnClickListener(new OnClickListener ());
threeStar.setOnClickListener(new OnClickListener ());
fourStar.setOnClickListener(new OnClickListener ());
fiveStar.setOnClickListener(new OnClickListener ());
}
}
Any help would be appreciated.
Thanks in advance.
You should not be looking at two different activities for tablet and phone. There are different resource layout folders for this exact purpose. You create a layout for landscape in layout-land and your portrait is just in the normal layout folder. Then you have just one activity and the OS chooses the layout to use based on the screen and orientation
Your layout should be flexible to adapt to different sizes. You should have only a single layout for all sizes, avoid hardcoded sizes.
This is an excerpt from https://developer.android.com/training/multiscreen/screensizes
"Avoid hard-coded layout sizes. To ensure that your layout is flexible and adapts to different screen sizes, you should use "wrap_content" and "match_parent" for the width and height of most view components, instead of hard-coded sizes.
"wrap_content" tells the view to set its size to whatever is necessary to fit the content within that view.
"match_parent" makes the view expand to as much as possible within the parent view."

Adding a webview programmatically

I have had no trouble adding a web view to my layout on click with a button, but when it comes to adding a web view on create of my main activity it just does nothing. I need the program to create certain web views based on data stored when I run it. It just really gets me that the same exact code runs perfectly when I put it inside an onClick button, but in the main method it does absolutely nothing. No error, no anything.
tickerLinearLayout = (LinearLayout) findViewById(R.id.TickerLinearLayout);
currency = new WebView(this);
currency.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, btcUp.getMeasuredHeight()));
tickerLinearLayout.addView(currency);
currency.getSettings().setJavaScriptEnabled(true);
disableScroll(currency);
currency.loadUrl("file:///android_asset/btc.html");
To create a Webview programatically in an Activity, you will first have to add your Webview into a RelativeLayout. I am choosing a RelativeLayout because my use case needs the Webview to be positioned on different locations on the Parent View time to time.
public class CustomRelativeLayout extends RelativeLayout {
private WebView mWebView;
public CustomRelativeLayout(Context context) {
super(context);
mWebView = new WebView(context);
mWebView.setId(View.NO_ID);
mWebView.setScrollContainer(false);
mWebView.loadData("<html><body>TEST</body></html>", "text/html", "utf-8");
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
context.getResources().getDisplayMetrics().widthPixels, context.getResources().getDisplayMetrics().heightPixels);
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
mWebView.setLayoutParams(params);
addView(mWebView);
}
public WebView getTheWebView() {
return mWebView;
}
}
You can modify the CustomRelativeLayout class to accept URL.
In your MainActivity class, you will have to add a new instance of CustomRelativeLayout and add it to the contentView as shown below:
setContentView(new CustomRelativeLayout(this));
To make adjustments to the size of the webview play around with the width and height of the LayoutParams added to the Webview.
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
<width>, <height>);

How does setContentView work in android?

I am trying to display a button on my android app but everytime i run the app it crashes. i realise this is because i use setContentView multiple times? I dont understand how it works, and dont understand how i can fix this problem so my button will display. my code is below.
public class MainActivity extends Activity {
Draw draw;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
draw = new Draw(this);
draw.setBackgroundColor(Color.BLUE);
setContentView(draw);
LinearLayout l = new LinearLayout(this);
l.setOrientation(LinearLayout.VERTICAL);
setContentView(l);
l.addView(new Draw(this));
//setContentView(R.layout.activity_main);
setUpBlockBtn();
}
private void setUpBlockBtn(){
setContentView(R.layout.activity_main);
Button addBlockButton = (Button)findViewById(R.id.btnBlock);
addBlockButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i("DemoButtonApp", "you clicked the button");
//finish();
}
});
}
You try to access Button from android xml layout but you do not set this layout in Activity.
Put you button activity_main.xml and use this button in your activity.
Thanks
You can create one more layout and add Draw and Linear layout to that layout.
Something like this.
LinearLayout l1=new LinearLayout(this);
l1.setOrientation(LinearLayout.VERTICAL);
l1.addView(draw);
l1.addView(l2) // your linearLayout.
setContentView(l1)
Remember you can't use setContentView more than one time.
There should be top layout which includes subview and other layouts and then you can add that layout to your activity.

How to transfer data between Views in a Layout

I haven't beeen able to find the answer to the following question:
How do I get data from View A to View B, with View A and View B in the same LinearLayout? Is this even possible? Do I need to start working with threads?
I haven't been able to get the correct search phrase I guess, I'm probably not the first person that wants to do this, but I can't find it :(
Below is what I use now to create the views. In the TargetTrainer (which extends View) I'm letting the user give some input, and I'd like to be able to give feedback to the user in the TextView. How would I for instance show the coordinates of the onTouchEvent of TargetTrainer in the TextView?
Below is a clipped/simplified version of my program.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
LinearLayout linear;
linear = new LinearLayout(this);
linear.setOrientation(LinearLayout.VERTICAL);
TextView text = new TextView(this);
text.setText("Test");
linear.addView(text);
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
TargetTrainer t = new TargetTrainer(this, width, height);
linear.addView(t);
setContentView(linear);
}
As I can see from the snippet, you already pass Context in the constructor new TargetTrainer(this, width, height). Assuming that the code you provided is from activity called BaseActivity create reference to BaseActivity in the TargetTrainer constructor and call the update method from TargetTrainer.
public TargetTrainer extends View {
....
BaseActivity mBaseActivity = null;
public MyView(Context context, int width, int height) {
....
mBaseActivity = (BaseACtivity)context;
....
}
....
private void update(String text)
{
mBaseActivity.updateTextView(text);
}
}
In BaseActivity create updateTextView:
public void updateTextView(String updateText){
text.setText(updateText);
}
You should set the id of that TextView, listen to the touch events in your TargetTrainer, and when one occures, you use
final TextView tv = (TextView)TargetTrainer.this.findViewById(R.id.myTextView);
tv.setText(touchEvent.toString());
That's it.
Update
It would be much cleaner, if you'd build your main layout from an xml source.
You need to create a new layout xml inside the /res/layout that looks like the one you're creating inside your onCreate method:
res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="#+id/myTextView" android:text="Test"
android:layout_width="fill_parent" android:layout_height="wrap_content" />
<!-- change the your.package part to match the package declaration
of your TargetTrainer class -->
<your.package.TargetTrainer android:id="#+id/myTargetTrainer"
android:layout_width="fill_parent" android:layout_height="fill_parent" />
</LinearLayout>
This way a new entry will be placed inside your R class' static layout class with the name main.
You can reference it by R.layout.main.
Note, that in this xml you have id attributes defined for both
your TextView: myTextView, and
your TargetTrainer:
'myTargetTrainer'.
The #+id inside the xml tag means that you are creating a new id with the name after the '/' sign.
This also will create new members inside your R class' static id class with the names you've provided: myTextView and myTargetTrainer that are accessible from now on from anywhere in your code.
If you've built this xml, your onCreate method will look like this:
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// attach the OnTouchListener to your TargetTrainer view:
(TargetTrainer)findViewById(R.id.myTargetTrainer).setOnTouchListener(this);
}
You also have to extend your main activity class to implement the View.OnTouchListener interface, and add the necessary method at the end of your class:
#Override
public boolean onTouch(View view, MotionEvent event)
{
//note, that here the view parameter is the view the touch event has been dispatched to
final TextView tv = (TextView)findViewById(R.id.myTextView);
tv.setText(event.toString());
return true; //or false, if you are dealing further with this event in parent classes
}

addView into a linearlayout in a scrollview is erased on refresh

I am currently working on a line entry calculator application for android. When the Button "button" is clicked it should add two textviews into the linearlayout "holder_main_layout" which is within a scrollview. One of the textviews is the text value of an edit text to the left, the other is the evaluated answer to the right. All of this works, but when I reorient the phone (from vertical to landscape or landscape to a different landscape) the linear layout is blank again. I know its not smart to leave all of those textviews without a way to access them but this is proof of concept at the moment.
Why is the scrollview empty when I rotate the phone. And how can i prevent this from happening.
public class main extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final LinearLayout holder_main_layout=(LinearLayout)findViewById(R.id.linearLayout2);
final CalculatorBase calc=new CalculatorBase();
final Button button = (Button) findViewById(R.id.button1);
final ScrollView scroller=(ScrollView)findViewById(R.id.scrollView1);
final main self=this;
final EditText input_text=(EditText)findViewById(R.id.editText1);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
TextView input_view=new TextView(self);
input_view.setText(input_text.getText());
holder_main_layout.addView(input_view);
TextView output_view=new TextView(self);
output_view.setText(String.valueOf(calc.eval_expression(input_text.getText().toString())));
output_view.setGravity(5);
holder_main_layout.addView(output_view);
input_text.setText("");
scroller.fullScroll(ScrollView.FOCUS_UP);
}
});
}
}
By default Android destroys and re-create Activity when orientation changes. You can do two things:
save state as described here: https://developer.android.com/reference/android/app/Activity.html#SavingPersistentState
handle screen orientation change yourself: https://developer.android.com/guide/topics/resources/runtime-changes.html
Try the second method first. Modify your manifest to include android:configChanges line in Activity definition:
<activity android:name=".MyActivity"
android:configChanges="orientation|keyboardHidden"
android:label="#string/app_name">
Then place following method in Activity code:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}

Categories