I'm trying to write an application that’s adding buttons dynamically.
The application receives an image from the server and adding a button (no functionality for now).
The main activity is holding linear layout which will contain the buttons and a surface view that would receive the images and would create the buttons in the main activity.
The problem is that after the first image has been received the application crash while trying to add a new button to the view.
This is the surface view code:
public void run() {
while ( isRunning){
if ( !ourHolder.getSurface().isValid()){
continue;
}
Canvas canvas = ourHolder.lockCanvas(); // Semafor for the canvas
canvas.drawRGB(20,20,80);
if (getNumOfBoards() > 0){
canvas.drawBitmap(getCurrentBoard(), 0, 0, null);
}
ourHolder.unlockCanvasAndPost(canvas);
}
}
This is the Main Activity add button code
public void addButtons(int numOfButton) {
// create patameter
LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
// create new button
Button newbutton = new Button(this);
// set background color
newbutton.setBackgroundColor(Color.BLUE);
// set width and height
newbutton.setWidth(30);
newbutton.setHeight(20);
// set position
newbutton.setY((float)numOfButton*20);
newbutton.setX(0);
// set text
newbutton.setText("new button");
// add button to the layout
buttons.addView(newbutton,p);// **the application crash here**
}
Due to the way android handles the Activities, the constructor onCreate is not guaranteed to have been called every time the addButtons method is executed
(See the Activity Lifecycle Section at developer.android.com)
You had better find the buttons LinearLayout
LinearLayout buttons = (LinearLayout) findViewById(R.id.LayoutButtons);
in addButtons and add the new button.
Related
I am using an library called CircularFloating to show menu in my homepage in one fragment but when i click and go to the next fragmetn it still appears to be in next fragment also. how can I remove or set visibility off when I move to next fragments.
here is my code.
SubActionButton.Builder itemBuilder = new SubActionButton.Builder(getActivity());
ImageView itemIcon1 = new ImageView(getActivity());
itemIcon1.setImageDrawable(getResources().getDrawable(R.drawable.camera_button));
SubActionButton button1 = itemBuilder.setContentView(itemIcon1).build();
ImageView itemIcon2 = new ImageView(getActivity());
itemIcon2.setImageDrawable(getResources().getDrawable(R.drawable.button_action_dark_touch));
SubActionButton button2 = itemBuilder.setContentView(itemIcon2).build();
final FloatingActionMenu actionMenu = new FloatingActionMenu.Builder(getActivity())
.addSubActionView(button1)
.addSubActionView(button2)
.attachTo(actionButton)
.build();
itemIcon2.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
Fragment abt = new Feedback_Fragment();
((AppCompatActivity)getActivity()).getSupportFragmentManager().beginTransaction().replace(R.id.frame_container, abt).addToBackStack(null).commit();
actionMenu.close(true);
}
});
Library I have used is
implementation 'com.oguzdev:CircularFloatingActionMenu:1.0.2'
You can remove the visibility with
actionMenu.setVisibility(View.INVISIBLE)
or
actionMenu.setVisibility(View.GONE)
And set the visibility to visible again with
actionMenu.setVisibility(View.VISIBLE)
Without knowing exactly how this library is built, you could try playing around with the attribute
app:elevation="0". Try to set this attribute to the layout that is currently appearing on top of all fragments, if this attribute is available for that layout. If not, try setting it for the FloatingActionButtons. Hope this helps.
{Visual Aid}
I am making an application with a drag and drop menu. User can fill out three edit texts (width, height, and rotation) then press on "add new" button and a new button with the specified values is created at the origin. However if the rotation attribute is anything other than 0 say 45 degrees, then it rotates the whole button along with the text. I would like for the text to remain horizontal with no rotation. I have looked up but the post all refer back to the rotation attribute which i am already using.
onViewCreated()
tvAddTable = view.findViewById(R.id.btn_add_table);
tvWidth = view.findViewById(R.id.et_width);
tvHeight = view.findViewById(R.id.et_height);
tvRotation = view.findViewById(R.id.et_rotation);
mSize = new Point();
mDisplay = Objects.requireNonNull(getActivity()).getWindowManager().getDefaultDisplay();
mDisplay.getSize(mSize);
final View.OnTouchListener touchListener = this;
tvAddTable.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {[enter image description here][1]
ConstraintLayout layout = view.findViewById(R.id.floor_layout);
//set the properties for button
Button btnTag = new Button(getContext());
btnTag.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
if(ids.isEmpty()){
ids.add(0);
}else{
ids.add(ids.size());
}
btnTag.setId(ids.size());
btnTag.setText(Integer.toString(btnTag.getId()));
//add button to the layout
layout.addView(btnTag);
btnTag.setLayoutParams(new ConstraintLayout.LayoutParams(Integer.parseInt(tvWidth.getText().toString()), Integer.parseInt(tvHeight.getText().toString())));
btnTag.setRotation(Integer.parseInt(tvRotation.getText().toString()));
btnTag.setOnTouchListener(touchListener);
}
});
The rotation attribute rotates the entire view, not just the text or just the background. That's by design. There is no text or background rotation attribute. If you need that, make a custom view.
If you only want the background to rotate, you can probably do it by setting the background drawable to a RotateDrawable that wraps the background you want.
I want to make an app that can create notification on the screen on top of anything that is currently being displayed. Something like the Go SMS message popup or something like the ChatHead in the following picture:
It would be even better if it is possible to draw it dynamically including touch events.What is the conventional or standard way to do this?
Example:
Like an Icon that can be clicked or dragged no matter whether you are on home screen or app drawer or other apps.Pay attention to the circular icons near the edges of the screen in the picture posted. You can drag them anywhere in any app.
What you are looking for is System Alert Window.
There's a library called StandOut! which will assist you in creating such apps.
Here is how things like Toast and dialog windows work:
In the case where just adding or bringing to front does not work, say when you are having a service add its own view to another client activity or application (FaceUnlock does this), or you cannot depend on hierarchies, you need to use the window manager and a window token to do the trick. You can then create layouts and take advantage of animations and hardware acceleration as before.
WindowManager windowManager = (WindowManager) getBaseContext().getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.FIRST_SUB_WINDOW);
layoutParams.width = 300;
layoutParams.height = 300;
layoutParams.format = PixelFormat.RGBA_8888;
layoutParams.flags =
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
layoutParams.token = getWindow().getDecorView().getRootView().getWindowToken();
//Feel free to inflate here
mTestView = new View(this);
mTestView.setBackgroundColor(Color.RED);
//Must wire up back button, otherwise it's not sent to our activity
mTestView.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
onBackPressed();
}
return true;
}
});
windowManager.addView(mTestView, layoutParams);
Then be sure to remove the view onDestroy (or onPause) or you will crash
if (mTestView != null) {
WindowManager windowManager = (WindowManager) getBaseContext().getSystemService(Context.WINDOW_SERVICE);
if (mTestView.isShown()) {
windowManager.removeViewImmediate(mTestView);
}
}
You don't need a new activity to do this. All you need to do is to add another view into your existing activity and bring it to the front, and draw/write the things that you want into that view.
If you want to do special things with this extra view, you could create your own view class
class DrawOnTop extends View {
public DrawOnTop(Context activity) {
super(activity);
}
#Override
protected void onDraw(Canvas canvas) {
// put your drawing commands here
}
}
and then you do something like
DrawOnTop mDraw = new DrawOnTop(this);
addContentView(mDraw, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
mDraw.bringToFront();
Then to force it to draw, you need to use mDraw.invalidate();
You could have the parent of your whole layout as RelativeLayout. The first child being the "root" of your main layout. Anything after that can be considered an overlay which is placeable to your whims.
Example:
<RelativeLayout>
<LinearLayout>
... Main Layout here ...
</LinearLayout>
<TextView left="20dip" top="20dip" text="Overlay" alpha="0.7" />
</RelativeLayout>
The best way is to start a service with your application.
Create an ImageView.
Set the LayoutParams of the Image View.
Add the view along with the params to the window manager when the service is created.
ALL SET
Your Image sticks to your window (At any screen over all apps), till you application is closed.
You can even add onclicklisteners and ontouchlisteners to the imageview.
Eg. OnClick listeners to perform some actions and Ontouchlisteners move the image along the screen.
In my app I have 4 main buttons, plus another 2. These 4 buttons are declared at the beginning of the main activity.
Button button1, button2, button3, button4;
button1 = (Button) findViewById(R.id.button1);
button1.setTag("blue");
(each button has a tag and is set the same way as button1)
The four buttons I want to cycle through different colours when they are pressed. I manage this by;
public void button1(View v) {
if ("blue".equals(button1.getTag())) {
button1.setBackgroundDrawable(getResources().getDrawable(
R.drawable.brown));
button1.setTag("brown");
} else if ("brown".equals(button1.getTag())) {
button1.setBackgroundDrawable(getResources().getDrawable(
R.drawable.red));
button1.setTag("red");
} else if //...etc
This works all well and good until I press any of the two buttons, an example code of one of the buttons
public void back(View v) {
setContentView(R.layout.main);
t = new TextView(this);
t = (TextView) findViewById(R.id.textView1);
t.setText("");
}
Once I press any of the two buttons the colours change back to the original drawable set in the xml file
android:background="#drawable/blue"
Now when I press the 4 main buttons the drawable does not change, but I definitely know that it is getting re-tagged, so why won't it change the drawable after I press the button?
If your 'two buttons' onClick handler makes a call to Activity.setContentView(int), then all of the buttons will reset to how they are specified in the original XML layout. New views will be inflated and these will not have a tag (you do not seem to be re-setting the tags after the call to setContentView). A null tag will not match any of your colour strings and so your buttons will not cycle their background.
If you want to maintain the views how they were, then do not reset the content view of the Activity. In most cases, setContentView is only called once per lifetime of an Activity, although obviously there can be a few exceptions.
I have a button that I have created in code, which has a listener for Click events. Every time that the button is clicked, it should generate another button and add it below the original button. However, no matter how many times I click the first button, it will only add a dynamic button once, and not add any more.
Here is my coding:
public class DynaminControlActivity extends Activity {
private RelativeLayout container;
private int mainIdCnt = 0;
private int mainId = 100;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
createMainButton();
}
public void createMainButton() {
container = (RelativeLayout) findViewById(R.id.workLayout);
Button b = new Button(this);
b.setId(mainIdCnt + mainId);
CharSequence text = "Main +";
b.setText(text);
container.addView(b);
if (mainId > 0) {
mainId++;
}
b.setOnClickListener((new View.OnClickListener() {
public void onClick(View v) {
createDynamicButton();
}
}));
}
public void createDynamicButton() {
container = (RelativeLayout) findViewById(R.id.workLayout);
Button b = new Button(this);
CharSequence text = "Main +";
b.setText(text);
RelativeLayout.LayoutParams relLayout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
relLayout.addRule(RelativeLayout.BELOW, mainIdCnt + mainId);
container.addView(b, relLayout);
if (mainId > 0) {
mainId++;
}
}
A few things...
If your main layout is a LinearLayout, you shouldn't need to add a rule to indicate that the button should appear underneath the existing button - it will automatically be added to the very bottom (vertical alignment) or very right (horizontal alignment) of the layout.
All your buttons have the same text. Are you certain that you're clicking the first button each time? I note that only your first button has a listener on it, so if you're accidentally clicking one of the other buttons then nothing will happen.
If you're intending to add multiple buttons, it will quickly expand to be larger than the screen size, so you should make sure that your main layout is within a ScrollView so that you can see all the buttons you add
The call to setId() might be stuffing around with the internal workings of Android. Rather than setting an ID, you should let Android generate the ID automatically, and just retrieve that value if you need to reference it.