Android Studio: Getting id of Dialog TextView in another class? - java

I'm trying to create a couple of Progress Bars inside a Dialog "remaining_amount_report" in Activtiy A:
public void setProgressBars(){
ProgressBar_Setup setup = new ProgressBar_Setup();
setup.createProgressBar(1, "product1", 80);
setup.createProgressBar(2, "product2", 60);
setup.createProgressBar(3, "product3", 100);
setup.createProgressBar(4, "product4", 20);
}
Therefore I've created a Class "ProgressBar_Setup" where the Method is reachable.
But the problem is, since I want to overwrite some TextView Texts of the Dialog, I need to get access to the Dialog inside the Class.
The Class extends Activity A, so I normally should get access just like this:
public void createProgressBar(int position, String productname, int progress) {
mposition = position;
switch(mposition){
case 1:
progressbar[0].setProductname(((TextView) remaining_amount_report.findViewById(R.id.remaining_amount_productname_1)));
But I get an Null Object Reference Error, by doing this.
Then I tried a different way, by adding a Dialog Variable to the "createProgressBar"-Method (not really good behavour, I guess):
public void setProgressBars(){
ProgressBar_Setup setup = new ProgressBar_Setup();
setup.createProgressBar(1, "product1", 80, remaining_amount_report);
setup.createProgressBar(2, "product2", 60, remaining_amount_report);
setup.createProgressBar(3, "product3", 100, remaining_amount_report);
setup.createProgressBar(4, "product4", 20, remaining_amount_report);
And in the ProgressBar_Setup-Class
public void createProgressBar(int position, String productname, int progress, Dialog dialog) {
mposition = position;
switch(mposition){
case 1:
progressbar[0].setProductname(((TextView) dialog.findViewById(R.id.remaining_amount_productname_1)));
But still the same error.
Could you help me here?
Thank you!

I think you need to use findViewById to first link the views in progressbar.

Related

How to pass object through activities by reference?

this is my first post here so be gentle :p
Here is the thing, I'm facing a really though issue and after several research i did not manage to figure out a clean solution. Let me explain:
I'm actually developing an android app for restaurant management.
In activity A, i'm able to create some articles with different parameters (picture, name, price ..).
I can also create a menu in which i indicate which articles are included. To do so i run Activity B that contains a dynamic list of the available articles (the ones i created) to be chosen. After picking up some of them the customised chosen objects are sent to Activity A through Parcel. And the chosen article list is updated in the menu.
But here is the thing, as far as i know, using Parcels create another instance of the object. As a result, if i modify or delete an article, the article list included in the menu does not change, and obviously i would like the list in the menu to be automatically updated.
Is there a way to simply pass customised objects through activities by reference?
What could be a clean solution to make the article list in the menu dynamic?
Here is some code:
In Activity A, in the menu interface i click + button to add an article, which run Activity B (the extras is the list of articles already included in the menu before, so in the beginning it's empty).
//Add article
FloatingActionButton addArticleButton = (FloatingActionButton)parentActivity.findViewById(R.id.addArticleButton);
addArticleButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showMenuDetails(menuListView,menuAdapter,currentMenu);
parentActivity.startActivityForResult(new Intent(parentActivity.getApplicationContext(),ChooseArticleActivity.class).putParcelableArrayListExtra("menuArticleList",currentMenu.getArticles()),PICK_ARTICLES);
}
});
In activity B: I select Articles in a list of available Articles (the ones i created). After picking up i press OK button to put the list of chosen articles in result Intent as Parcelable Extras
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.choose_article_layout);
initializeLists();
this.resultIntent = new Intent();
}
private void initializeLists(){
final ListView articleToChoose = (ListView)findViewById(R.id.articleToChoose);
final ListView articleChosen = (ListView)findViewById(R.id.articleChosen);
final ArrayList<Article> articleToChooseList = (ArrayList<Article>)MainActivity.model.getArticleList().getArticleList().clone();
final ArrayList<Parcelable> articleChosenListParcelable = (ArrayList<Parcelable>)this.getIntent().getParcelableArrayListExtra("menuArticleList");
final ArticleAdapter articleToChooseAdapter = new ArticleAdapter(getApplicationContext(), articleToChooseList);
articleToChoose.setAdapter(articleToChooseAdapter);
ArrayList<Article> articleChosenListTemp = new ArrayList<>();
ArrayList<Article> articleToRemove = new ArrayList<>();
for(Parcelable a:articleChosenListParcelable){
articleChosenListTemp.add((Article)a);
for(Article article:articleToChooseList){
if(article.getName().equals(((Article) a).getName())){
articleToRemove.add(article);
}
}
}
articleToChooseList.removeAll(articleToRemove);
articleToChooseAdapter.notifyDataSetChanged();
final ArrayList<Article> articleChosenList = articleChosenListTemp;
final ArticleAdapter articleChosenAdapter = new ArticleAdapter(getApplicationContext(),articleChosenList);
articleChosen.setAdapter(articleChosenAdapter);
articleChosen.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Article articleClicked = articleChosenAdapter.getItem(position);
articleChosenList.remove(articleClicked);
articleToChooseList.add(articleClicked);
articleChosenAdapter.notifyDataSetChanged();
articleToChooseAdapter.notifyDataSetChanged();
}
});
articleToChoose.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Article articleClicked = articleToChooseAdapter.getItem(position);
if(!articleChosenList.contains(articleClicked)){
articleChosenList.add(articleClicked);
articleToChooseList.remove(articleClicked);
articleToChooseAdapter.notifyDataSetChanged();
articleChosenAdapter.notifyDataSetChanged();
}
}
});
Button okButton = (Button)findViewById(R.id.okButton);
okButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
chosenArticleListAttr = articleChosenList;
resultIntent.putParcelableArrayListExtra("articleList",chosenArticleListAttr);
setResult(RESULT_OK,resultIntent);
finish();
}
});
Button cancelButton = (Button)findViewById(R.id.cancelButton);
cancelButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
}
In activity A, in onActivityResult i catch the result and update the list, but the added Articles here are not the same instance as the article list in the model
if(requestCode==PICK_ARTICLES && resultCode==RESULT_OK){
ArticleAdapter articleAdapter = (ArticleAdapter) gestionMenusLayout.getMenuArticleListView().getAdapter();
ArrayList<Parcelable> chosenArticleList = (ArrayList<Parcelable>)data.getParcelableArrayListExtra("articleList");
gestionMenusLayout.getCurrentMenu().getArticles().clear();
for(Parcelable a:chosenArticleList){
gestionMenusLayout.getCurrentMenu().addArticle((Article)a);
}
articleAdapter.notifyDataSetChanged();
}
For debugging purpose only, I suggest that you use a public static List<Article> articleList and call it directly from whether activity A or B
A better but take-alittle-more-effort solution is that you store the list in a database, and every updates, queries, ... come through it.You can use the server's database (where people usually get articles from), or a offline database like Realm here
I figured it out with a quite easy and simple solution finally.
I keep passing my Article objects through intents by parcels.
But as it creates a new instance, instead of adding this instance i add the original one (the one from the model) after an equality key check (the name of the article). By doing so i keep the reference on my Article.
Thank you for helping!
Edit:
Here is the code:
if(requestCode==PICK_ARTICLES && resultCode==RESULT_OK){
ArticleAdapter articleAdapter = (ArticleAdapter) gestionMenusLayout.getMenuArticleListView().getAdapter();
ArrayList<Parcelable> chosenArticleList = (ArrayList<Parcelable>)data.getParcelableArrayListExtra("articleList");
gestionMenusLayout.getCurrentMenu().getArticles().clear();
ArrayList<Article> modelArticles = MainActivity.model.getArticleList().getArticleList();
for(Parcelable a:chosenArticleList){
for(Article modelArticle:modelArticles){
if(((Article)a).getName().equals(modelArticle.getName())){
gestionMenusLayout.getCurrentMenu().addArticle(modelArticle);
}
}
}
articleAdapter.notifyDataSetChanged();
}

Click effect/animation for all application

It is possible to create a click effect/animation for all clicks on my application?
Since I want this behaviour for all clicks events on my application, how should I do this? Is this bad for performance or resources of the smartphone?
It is hard to know without understanding the stack that has been built, that being said I think there are some safer and less methodologies to an onclick event that is the same across the board. For one I would not change fundamental nature of the "onClick" function, the lower level you mess with the more dangerous it is. That being said I think I would create my own version/function of onclick, maybe boomClick, where boomClick creates the animation that you want. Referencing a single function will barely decrease performance at all.
So, after a day working at this I managed to accomplish the expected behaviour.
Basically, I create my own Activity class which will do the animation work with the help of a custom lib. I'll try to explain what I did for future reference:
1. Add this lib to your project:
compile 'pl.droidsonroids.gif:android-gif-drawable:1.2.3'
2. Add these dimens to your "dimens.xml" file:
<dimen name="click_animation">100dp</dimen>
<dimen name="click_compensation">50dp</dimen>
3. Make the top parent of your activities layout a "RelativeLayout" and set a custom id:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/main_layout">
... the rest of the layout ...
</RelativeLayout>
4. Create your own "Activity" class:
public class MyActivity extends AppCompatActivity {
private RelativeLayout.LayoutParams params;
public void setClickAnimation(final Activity activity) {
// if you want to change the size of the animation, change the size on the dimens.xml
int size = (int) activity.getResources().getDimension(R.dimen.click_animation);
params = new RelativeLayout.LayoutParams(size, size);
// you want the parent layout of the activity
final RelativeLayout view = (RelativeLayout) activity.findViewById(R.id.main_layout);
view.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// you maybe won't need this compensation value
int compensation = (int) activity.getResources().getDimension(R.dimen.click_compensation);
try { startAnimation(view, (int) event.getX() - compensation, (int) event.getY() - compensation); }
catch (IOException e) { e.printStackTrace(); }
}
return true;
}
});
}
private void startAnimation(RelativeLayout view, int x, int y) throws IOException {
params.leftMargin = x;
params.topMargin = y;
// those are from the lib you imported
final GifImageView anim = new GifImageView(this);
// if you don't have it yet, put the gif you want on the assets folder
final GifDrawable gifFromResource = new GifDrawable(getAssets(), "click_animation.gif");
gifFromResource.addAnimationListener(new AnimationListener() {
#Override
public void onAnimationCompleted(int loopNumber) {
anim.setVisibility(View.GONE);
gifFromResource.stop();
gifFromResource.recycle();
}
});
anim.setBackground(gifFromResource);
gifFromResource.start();
view.addView(anim, params);
}
}
5. Make your Activities extend your "Activity" class:
public class FirstScreen extends MyActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.cards_screen);
// call the method you created and pass the activity context
setClickAnimation(this);
}
}
As for resources spent: this looks like a good solution and I am getting a good performance. The application seems to not be wasting a lot of resources with this solution.

Set properties of multiple views at once

For example, if I have:
EditText A;
TextView B;
ImageView C;
And I want to set all their visibilities to View.GONE, how can I do it in a way that instead of this:
A.setVisibility(View.GONE);
B.setVisibility(View.GONE);
C.setVisibility(View.GONE);
I do this:
groupD.setVisibility(View.GONE);
without having to put all of them in one RelativeLayout and then setting the RelativeLayout to View.GONE? Is there a Java class for this? Or do I have to get a library for it?
If not, can I do it manually so I can organize my project which has 30 views? I don't want to set each group to be in its own RelativeLayout because all views are dependent on each other.
With ButterKnife you can do:
#BindViews({ R.id.A, R.id.B, R.id.C })
List<View> views;
ButterKnife.apply(views, VISIBLE);
ButterKnife.apply(views, GONE);
//Action and Setter interfaces allow specifying simple behavior.
static final ButterKnife.Action<View> VISIBLE = new ButterKnife.Action<View>() {
#Override public void apply(View view, int index) {
view.setVisibility(View.VISIBLE);
}
};
static final ButterKnife.Action<View> GONE = new ButterKnife.Action<View>() {
#Override public void set(View view, int index) {
view.setVisibility(View.GONE);
}
};
Example adapted from the website
The best way will be passing the views to a single method. All of them are Views, so you can do something like this.
public void setViews(View view){
view.setVisibility(View.GONE);
}
And call the method like this:
setViews(editText);

How do you delay the return statement of a function?

I have a piece of code where a function opens a popup window to later return an integer based on what happened inside that window. But when I run it, it directly returns the integer without opening any popup window.
How do I tell that function to wait to return until a user has done a certain action?
Here's the code in case you need it:
public int initPopup(String monsterName, String monsterHP){
final int monsterHPInt = Integer.parseInt(monsterHP);
PopupWindow popup;
TextView popupText;
Button closePopupButton;
final SeekBar monsterHPChanger;
LinearLayout popupLayout;
popupText = new TextView(this);
popupText.setText(monsterName);
monsterHPChanger = new SeekBar(this);
monsterHPChanger.setMax(monsterHPInt);
/** Will only use if necessary
* monsterHPChanger.setProgress(monsterHPChanger.getMax());
*/
popupLayout = new LinearLayout(this);
popupLayout.setOrientation(LinearLayout.VERTICAL);
popupLayout.addView(popupText);
popupLayout.addView(monsterHPChanger);
//TODO: Create the layout of the popup and the popup itself
popup = new PopupWindow(popupLayout, LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
popup.setContentView(popupLayout);
//Creating encapsulation class to edit the monsterHP with the value of the SeekBar
final MonsterHP monsterHPObject = new MonsterHP(monsterHPInt, monsterHPChanger.getProgress());
closePopupButton = new Button(this);
closePopupButton.setId(R.id.closePopup);
closePopupButton.setText("Ok");
closePopupButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
monsterHPObject.update(monsterHPChanger.getProgress());
}
});
Log.println(1, "Method", "Returns " + monsterHPObject.getHP());
// TODO: reactivate when debug is done return monsterHPObject.getHP();
//Returning 0 for debug reasons
return 0;
}
I'm looking your code and I dont see the call "popup.show()" anywhere. Also, if you want to wait some time to perform an operation you can use the following code.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// your operations (open popup?)
}
}, **your_delay_time**);
Hope it helps you!!
Use a callback interface that you pass to your method.
When the user performs the action, call the appropriate callback method.

Android: finding button by id

I have a problem with finding buttons. I have an AlertDialog where I choose one of 5 options. When I choose an option I want change the color of the button I clicked. I declared buttons in xml file inside <RealativeLayout> but when I'm trying to find my button by id (id's are like "id1","id2"...)using the findViewById method, there is a mistake, which says that I can't use this method like I do:
AlertDialog.Builder builder = new AlertDialog.Builder(StartGameActivity.this);
builder.setTitle(R.string.pickColor);
builder.setItems(R.array.colorArray, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Button btn_tmp;
String theButtonId = "id";
theButtonId = theButtonId+(String.valueOf(which));
btn_tmp = (Button) findViewById(theButtonId);
}
});
How can I fix that or maybe I should use other method?
EDIT:
I think I solved my problem. I used one of Button's method: getId() like this:
final int id = clickedButton.getId();
final ImageButton btn_tmp;
btn_tmp = (ImageButton)findViewById(id);
Background: IDs are esentially variables
In the XML files we give IDs to the resources, and then the compilers use all these to generate the gen/R.java. So essentially, these IDs are int variables belonging in class R.
An example of R.java:
// btw this file should never be edited!
public final class R {
public static final class id {
public static final int id1=0x7f0100aa;
public static final int id2=0x7f0100ab;
}
}
Just because a String exists that contains a valid name of a variable (R.id.id1), it can't magically access that variable. To do this, one can use reflection. However, in this case I believe it is an unnecessary complication, and will even be slower.
findViewById needs an ID (integer variable):
You cannot supply a String to this function. You should use an integer value, and specifically the ones that correspont to int variables in R.java.
For example:
findViewById(R.id.id1) // for your 1st button
Solution:
You can dynamically select the integer value:
AlertDialog.Builder builder = new AlertDialog.Builder(StartGameActivity.this);
builder.setTitle(R.string.pickColor);
builder.setItems(R.array.colorArray, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Button btn_tmp;
int chosenID=-1;
switch (which) {
case 1: chosenID=R.id.id1;
break;
case 2: chosenID=R.id.id2;
break;
}
btn_tmp = (Button) findViewById(chosenID);
}
});
It is also suggested to use more explanatory IDs, like: buttonDoThis, buttonDoThat.
btn_tmp = (Button)findViewById(R.id.YourButtonId);
You are passing string instead of integer.
If you are using your own layout.xml for the dialog, you need to inflate it first and give the view to your dialog builder.
LayoutInflater layoutInflater = (LayoutInflater) StartGameActivity.this.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
final RelativeLayout customDialogView= (RelativeLayout) layoutInflater.inflate(R.layout.custom_dialog_view, null);
AlertDialog.Builder builder = new AlertDialog.Builder(StartGameActivity.this);
builder.setTitle(R.string.pickColor);
//give the custom view to your dialog builder.
builder.setView(customDialogView);
builder.setItems(R.array.colorArray, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Button btn_tmp;
switch(which){
//....cases
case 1:
btn_tmp = (Button) customDialogView.findViewById(R.id.button1);
//set the color of the button selected
break;
case 2:
btn_tmp = (Button) customDialogView.findViewById(R.id.button2);
//set the color of the button selected
break;
}
//....cases
}
});
You are trying to use findViewById() with a String that holds the variable name of the ID. Java doesn't support this kind of dynamic variable names since variable names are only known at compile time, not run time. What are you trying to do? You will need to find another way to solve this problem. Please explain further and we can give suggestions.

Categories

Resources