I have an activity and a class that implements a popup window. Using this tutorial I implemented the popup. I call the methods init() and popupInit() from the activity and everything else is in the class. My problem is that the popup does not show.
Here is the popup class:
public class PopupAudio implements OnClickListener {
LinearLayout layoutOfPopup;
PopupWindow popupMessage;
Button popRecord, popStopRecord, popPlay, popStopPlaying;
TextView popupText;
public void popupInit() {
popRecord.setOnClickListener(this);
popStopRecord.setOnClickListener(this);
popPlay.setOnClickListener(this);
popStopPlaying.setOnClickListener(this);
popupMessage = new PopupWindow(layoutOfPopup, LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
popupMessage.setContentView(layoutOfPopup);
}
public void init(Context context) {
popRecord = new Button(context);
popRecord.setId(112);
popStopRecord = new Button(context);
popPlay = new Button(context);
popStopPlaying = new Button(context);
layoutOfPopup = new LinearLayout(context);
popRecord.setText("REC");
layoutOfPopup.setOrientation(1);
layoutOfPopup.addView(popRecord);
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch(v.getId()) {
case 112:
break;
}
}
}
It is a school project so it is very important. Please help me, I'll be grateful :)
You need to call a method to actually show the popup on some event action or whenever you need it. Here are the different methods from the docs
Here is one example of using showAtLocation().
showAsDropDown(View anchor) may be the simplest depending on your needs. Just pass it the view you want it to attach to. Though, the other two give you more flexibility on where it shows.
Related
I've coded a custom dialog for my application but once I try to open it, I got a lag and the following message is displayed in the logcat console:
Skipped 31 frames! The application may be doing too much work on its main thread.
To lower the work, I've moved the Typeface loading to an AsyncTask but it doesn't solve my problem.
public class CustomDialog
{
private Context context = null;
private Dialog dialog = null;
private boolean cancelable = true;
private OnCancelListener cancelListener = null;
private Typeface latoFont = null;
private RelativeLayout layout_root = null;
private TextView text_title = null;
private TextView text_message = null;
private LinearLayout layout_buttons = null;
public CustomDialog(Context context)
{
this.context = context;
this.dialog = new Dialog(context, android.R.style.Theme_Translucent_NoTitleBar);
this.dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.dialog.setContentView(R.layout.dialog);
this.dialog.setCancelable(true);
layout_root = (RelativeLayout) dialog.findViewById(R.id.layout_root);
text_title = (TextView) dialog.findViewById(R.id.text_title);
text_message = (TextView) dialog.findViewById(R.id.text_message);
layout_buttons = (LinearLayout) dialog.findViewById(R.id.layout_buttons);
// Set background color
layout_root.setBackgroundColor(FlatUtils.transparentDark(FlatConstants.DOMIANT_COLOR));
// Set font
new TypeFaceTask(context, new TextView[]{text_title, text_message}).execute();
// Attach listener
layout_root.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view)
{
if (view.getId() != R.id.layout_root) return;
if (cancelable)
{
if (cancelListener != null) cancelListener.onCancel();
dialog.dismiss();
}
}
});
}
public void setTitle(String title)
{
text_title.setVisibility(View.VISIBLE);
text_title.setText(title);
}
public void setMessage(String message)
{
text_message.setVisibility(View.VISIBLE);
text_message.setText(message);
text_message.setMovementMethod(new ScrollingMovementMethod());
}
public void addButton(String value, final OnClickListener listener)
{
// Create button
FlatButton button = new FlatButton(context);
button.setText(value);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, dpToPx(40));
params.setMargins(0, dpToPx(10), 0, 0);
layout_buttons.addView(button, params);
// Set typeface
if (latoFont != null) button.setTypeface(latoFont);
// Attach listener
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view)
{
if (listener != null) listener.onClick(view);
dialog.dismiss();
}
});
}
public void setCancelable(boolean b)
{
cancelable = b;
dialog.setCancelable(b);
}
public void setOnCancelListener(OnCancelListener listener)
{
this.cancelListener = listener;
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog)
{
cancelListener.onCancel();
}
});
}
public void show()
{
dialog.show();
}
public void dismiss()
{
dialog.dismiss();
}
public interface OnCancelListener {
public void onCancel();
}
private int dpToPx(int dp)
{
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return (int)(dp * (metrics.densityDpi / 160f));
}
}
This is way I create a new dialog:
CustomDialog dialog = new CustomDialog(TestActivity.this);
dialog.addButton("Hello 1", null);
dialog.addButton("Hello 2", null);
dialog.addButton("Hello 3", null);
dialog.setTitle("Dummy dialog");
dialog.setMessage("Plop plop");
dialog.show();
So my question is: Is there a way to optimized this code ?
First of all i think you should try extending the Dialog class instead of wrapping it like this...Your code will be cleaner and more reusable and i think will yield some performance improvement. It wont take you much, most of the code will be the same, but its a general rule of thumb if you want a custom Dialog you should extend the existing elements, similar to when you create an Activity or Fragment you extend them :).
Also i dont know what you are actually doing with your layouts but i see you are getting the screen width and height and then setting margins etc...Such calculations can cause your frames to skip and i would advise you to try making the layout through xml. Trust me, just try playing with layout params through xml and i bet you will get the same result when it comes to margins padings and the overal look, and use the different layout folders(and dimens for margins and paddings for ex) for different screen densities and sizes to achieve the same look across all devices. Not to mention this will perform faster.
Edit 1:
Typefaces wont cause such problems.
I see you said you are running this on emulator?! Well thats the issue :) i can guarantee that wont happen on a real device. :)) its a common thing on the emulator. Always develop on real devices, only they can mimic all the real problems and bugs you will encounter.
But still listen to the advice's here and follow "best practices" when programming.
is it phone or emulator? (try to run on phone)
Best practice - to extend DialogFragment(Dialog)
Adding buttons from code is strange :) You can declare yor dialog ui using XML layout, inflate it and set inflated view as content in your dialog
You don't need to load Typeface in asynctask.
So my general suggestion is to learn best practices of creating dialogs.
In my app I have multiple TextViews (the number of this elements is changing on activity creation). I want to execute some function on touch of each element: for instance change the background. I try to avoid writing the same function for each element.
I would like it to work like jQuery so if I trigger some event that are from some class the this element changes.
I hope it is clear, thanks!
Have your activity implement OnClickListener, and then in the onClick method put your common code, and call setOnClickListener(this); on each of your TextViews.
If you have more than one type of View being clicked, enclose the TextView specific code in:
if(<name of the view parameter in your onClick method) instanceof TextView)
{
//Code here
}
EDIT
Another method would be to create your own Custom TextView and override the method in that itself. Something like:
public class MyTextView extends TextView {
//Various constructors go here
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//Do your stuff here, your textview has been touched
return true;
}
return super.onTouchEvent(event);
}
}
Then instead of using TextView tv = new TextView(context);, use MyTextView tv = new MyTextView(context);
simple:
onCreate( //...
// do your layout creation
TextView tv = new TextView(context)
tv.setOnClickListener(clickListener);
tv.setTag(0); // this tag can be any object. So feel free to add a KEY_string, or anything that u might use to later identify your view on the click listener.
tv = new TextView(context);
tv.setOnClickListener(clickListener);
tv.setTag(1);
} // finish on create
private OnClickListener clickListener = new OnClickListener() {
#Override
public void onClick(View v) {
int id = (Integer)v.getTag();
switch(id){
case 0):
// do stuff
case 1:
// do other stuff
}
};
you also can use several other listeners, depending on your needs, just use the auto complete on Eclipse to check all the options for tv.setOn...
I have a class which uses other classes to build up a FrameLayout. One is for Navigation through a building, the other for displaying schematics with sensors of it, and the other one to display sensordata. I build up the whole frame one time, and want to make the sensordata visible in the sensorview part of the frame. Lets say I have 5 sensors, and when I click on one the sensorview shows up the sensordata. I could just make 5 sensorviewframes on top of each other, initiating them invisible, and just make the one visible which was selected via a click on a sensor.
I wanted to ask, is it possible to change the LinearLayout containing the TextViews in a different class with an update method?
I already tried it, but with my code it doesn't work at the moment.
public static SensorBar Create_SensorBar_Layout(Context myContext, ObjectStructure objStruct, ObjectView objView, List<SensorDevice> listofCurrentSensordevices)
{
// Init
LinearLayout SensorBarLinearLayout = new LinearLayout(myContext);
LinearLayout.LayoutParams layoutParamsSensorBar = new LinearLayout.LayoutParams(
200, 653);
layoutParamsSensorBar.setMargins(5, 5, 5, 5);
SensorBarLinearLayout.setOrientation(LinearLayout.VERTICAL);
SensorBarLinearLayout.setLayoutParams(layoutParamsSensorBar);
SensorBarLinearLayout.setBackgroundResource(R.drawable.window_frame);
SensorBarLinearLayout.setPadding(4,4,4,4);
LinearLayout SensorBarData = new LinearLayout(myContext);
LinearLayout.LayoutParams layoutParamsSensorBarData = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
SensorBarData.setOrientation(LinearLayout.VERTICAL);
SensorBarData.setLayoutParams(layoutParamsSensorBarData);
//--- Button Headline ---
Button buttonNavBarHeadline = new Button(myContext);
buttonNavBarHeadline.setText("Sensordata");
buttonNavBarHeadline.setTextColor(Color.BLACK);
buttonNavBarHeadline.setBackgroundResource(R.layout.mainview_window_headline);
buttonNavBarHeadline.setTextAppearance(myContext, R.style.headline3);
//Layout buildup
SensorBarLinearLayout.addView(buttonNavBarHeadline);
SensorBarLinearLayout.addView(SensorBarData);
return new SensorBar(SensorBarLinearLayout, SensorBarData);
}
This is the Sensorbar, and I want to have the LinearLayout SensorBarData to be dynamically swapped out by clicking on the sensorbuttons.
public void updateSensorBar(Context myContext, ObjectStructure objStruct, List<SensorDevice> listofCurrentSensordevices, int activeSensor)
{
LinearLayout linearlayoutSensorvalueTextviews = new LinearLayout(myContext);
... (additional Textviews for Sensordata, which get added with addview())
setSensorBarData(linearlayoutSensorvalueTextviews);
}
This is used by an OnClick event.
public void setSensorBarData(LinearLayout SensorBarData) { this.dataSensorBar = SensorBarData; }
This is used by the updateSensorBar to update the LinearLayout.
I would be glad for any help.
Define an interface and use a callback to let the activity know that a sensor has been updated.
public Interface SensorUpdatedListener {
void onSensorUpdated();
}
In your SensorBar class.
ArrayList<SensorUpdatedListener > listeners = new ArrayList<SensorUpdatedListener >();
...
public void setSensorUpdatedListener(SensorUpdatedListener listener){
listeners.add(listener);
}
In your sensor bar update method:
for (SensorUpdatedListener listener:listeners){
listener.onSensorUpdated();
}
In your Activity:
public class Test extends Activity implements SensorUpdatedListener {
...
#Override
public void onCreate(Bundle savedInstanceState)
{
...
sensorBar.setSensorUpdatedListener(this);
...
}
public void onSensorUpdated(){
// do whatever you need to do
}
You could improve the SensorBar class by adding removeSensorUpdatedListener and checking that you do not add the same listener twice in setSensorUpdatedListener.
I want to create an array of buttons in my app. So how that can be done. Secondly, is it possible to interact with each button in an array of buttons? If so, how? Please suggest to me.
Regards
Anshuman
Inside you Activity do something like this:
LinearLayout linear = new LinearLayout(this);
linear.setOrientation(LinearLayout.VERTICAL);
ArrayList<Button> ab = new ArrayList<Button>();
for (Button b : ab) {
linear.addView(b);
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
};
setContentView(linear);
I have problem with handling dynamically created Buttons on Android. I'm creating N buttons and I have to do the same method when button is clicked but I have to know which button is clicked.
for (int i = 0; i < NO_BUTTONS; i++){
Button btn = new Button(this);
btn.setId(2000+i);
...
btn.setOnClickListener((OnClickListener) this);
buttonList.addView(btn);
list.add(btn);
Cucurrently I'm adding ID to every button and I'm using the method below to see which button was clicked. (line btn.setId(2000+i); and btn.setOnClickListener((OnClickListener) this);). This method is also implemented in the activity.
#Override
public void onClick(View v) {
switch (v.getId()){
case 2000: selectButton(0);
break;
...
case 2007: selectButton(7);
break;
}
}
This doesn't look good to me so i'm asking is there some better way to do this? or how to send some information to onclick event? any suggestions?
You could create a method that returns an onclickListener and takes a button as a parameter. And then use that method to set the onClicklistener in the first loop you have..
Update: code could be soemthing along these lines:
View.OnClickListener getOnClickDoSomething(final Button button) {
return new View.OnClickListener() {
public void onClick(View v) {
button.setText("text now set.. ");
}
};
}
as a method in the activity and then use it in the loop like this
button.setOnClickListener(getOnClickDoSomething(button));
I got one solution for this..
use this code in onCreate
linear = (LinearLayout) findViewById(R.id.linear);
LayoutParams param = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1.0f);
Button[] btn = new Button[num_array_name.length];
for (int i = 0; i < num_array_name.length; i++) {
btn[i] = new Button(getApplicationContext());
btn[i].setText(num_array_name[i].toString());
btn[i].setTextColor(Color.parseColor("#000000"));
btn[i].setTextSize(20);
btn[i].setHeight(100);
btn[i].setLayoutParams(param);
btn[i].setPadding(15, 5, 15, 5);
linear.addView(btn[i]);
btn[i].setOnClickListener(handleOnClick(btn[i]));
}
after onCreate create one method of return type View.OnClickListener like this..
View.OnClickListener handleOnClick(final Button button) {
return new View.OnClickListener() {
public void onClick(View v) {
}
};
}
Button.OnClickListener btnclick = new Button.OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Button button = (Button)v;
Toast.makeText(getApplicationContext(), button.getText().toString(),2).show();
}
};
call this listener by btn.setOnClickListener(btnclick);
View IDs should not be used for these purposes as View Ids are generated on compilation time depending on IDs defined in xml layout files.
Just place your own IDs in the setTag() method which is available at the View level (so Buttons inherit them). This "tag" can be anything that allow you to recognize a View from others. You retrieve its value with getTag().
instead use setTag() function to distinct easily.
for(int i=0;i<4;i++) {
Button btn = new Button(this);
btn.setTag(i);
btn.setOnClickListener(new View.OnclickListener() {
#Override
public void onClick(View v) {
int i=v.getTag();
switch(i) {
case 1: btn.setText(i);
break;
case 2: btn.setText(i);
break;
case 3: btn.setText(i);
break;
case 4: btn.setText(i);
break;
default: btn.setText("Others");
}
}
}
"This doesn't look good to me" why not? doesn't it work? You could also create a static member variable holding a list of all added buttons, and then look for the clicked button in that list instead.
I don't know why you would want to create N buttons, it looks like your value of N is greater than 10 at least, if you are not trying to show them all at once (I mean fit all of them into one single screen, no scrolling) you could try to recycle the invisible buttons just like we do for list view using a list view holder. This would reduce your memory footprint and boost performance, and differentiate the buttons based either on the text you set on them or a tag or you can even hold a reference to those small number of buttons.
Is preferable not to mess up with the ids, setTag and getTag methods were designed for that purpose, it's the fast and clean way to set a bunch of button listeners on a dynamic layout
This answer may you help:
https://stackoverflow.com/a/5291891/2804001
public class MainActivity extends Activity implements View.OnClickListener
{
LinearLayout linearLayout;
Button [] button;
View.OnClickListener listener;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
linearLayout=(LinearLayout)findViewById(R.id.parent_lay);
String[] array={"U123","U124","U125"};
int length=array.length;
System.out.println("11111111111111111111111111");
button=new Button[length];
for(int i=0;i<length;i++)
{
button[i]=new Button(getApplicationContext());
button[i].setId(i);
button[i].setText("User" + i);
button[i].setOnClickListener(this);
linearLayout.addView(button[i]);
}
}
#Override
public void onClick(View view)
{
view.getId();
Button button=(Button)findViewById(view.getId());
button.setText("Changed");
}
}