How to catch implicit menu 'Back' command? - java-me

I'm programming a J(2)ME app (actually a MIDlet) where more commands than command buttons available are shown on the screen and I'm stuck with this situation:
The mapping to concrete user interface constructs may also depend on
the total number of the commands. For example, if an application asks
for more abstract commands than can be mapped onto the available
physical buttons on a device, then the device may use an alternate
human interface such as a menu. For example, the abstract commands
that cannot be mapped onto physical buttons are placed in a menu and
the label "Menu" is mapped onto one of the programmable buttons.
http://docs.oracle.com/javame/config/cldc/ref-impl/midp2.0/jsr118/javax/microedition/lcdui/Command.html
So in this situation a Menu is auto-generated and a 'Select' and 'Back' choice added. The 'Back' choice is supposed to exit the menu and go back to the previous screen. This works in principle, problem is I need to catch it somehow and trigger a redraw, otherwise the screen goes blank.
So my question is: Is there a way to catch this 'implicit' (automatically added 'Back' command ?
Code example and result:
public class HelloWorld extends MIDlet
{
private Form helloFrm;
private Display display;
public HelloWorld() {
Command command1 = new Command("Cmd 1", Command.SCREEN, 1);
Command command2 = new Command("Cmd 2", Command.SCREEN, 0);
Command command3 = new Command("Cmd 3", Command.SCREEN, 0);
Command command4 = new Command("Cmd 4", Command.SCREEN, 0);
helloFrm = new Form("Hello World");
helloFrm.addCommand(command1);
helloFrm.addCommand(command2);
helloFrm.addCommand(command3);
helloFrm.addCommand(command4);
}
public void startApp()
{
display = Display.getDisplay(this);
display.setCurrent(helloFrm);
}
public void pauseApp()
{
}
public void destroyApp(boolean unconditional)
{
}
}
edit to add more detail:
As per my comment, I'm going back from a Form to Canvas in my app, that's where the screen blanking happens.
I've already added my own 'Back' command, this one works correctly as I can catch easily with CommandListener and treat accordingly (trigger a redraw). But now I have two 'Back' commands, the implicit one (blanking) and mine.
So the alternative version of the question is: Can I prevent the adding of the implicit 'Back' command somehow ?

You can't prevent the adding of the implicit 'Back' command, but you can redraw the screen from the call to Canvas.showNotify:
The implementation calls showNotify() immediately prior to this Canvas
being made visible on the display. Canvas subclasses may override this
method to perform tasks before being shown, such as setting up
animations, starting timers, etc. The default implementation of this
method in class Canvas is empty.

Related

How to test navigation from DialogFragment to another DialogFragment?

I'm using the Navigation component for my two DialogFragments and when I press a button on the first DialogFragment it is dismissed and then the second one is shown. I need to test that clicking this button will take me to the second dialog. I have a simple home fragment that is overlayed by the first DialogFragment at the start of the app. The following code is from the first DialogFragment.
/**
* Redirects users to another dialog after pressing button
*/
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
button.setOnClickListener {
if (findNavController().currentDestination?.id == R.id.firstDialogFragment) {
findNavController().navigateUp()
val action = HomeFragmentDirections.actionHomeFragmentToSecondDialogFragment()
findNavController().navigate(action)
}
}
}
This next bit of code comes from the developer's guide and only checks for the behavior of dismissing a DialogFragment back to the previous Fragment.
#RunWith(AndroidJUnit4::class)
class MyTestSuite {
#Test fun testDismissDialogFragment() {
// Assumes that "MyDialogFragment" extends the DialogFragment class.
with(launchFragment<MyDialogFragment>()) {
onFragment { fragment ->
assertThat(fragment.dialog).isNotNull()
assertThat(fragment.requireDialog().isShowing).isTrue()
fragment.dismiss()
fragment.requireFragmentManager().executePendingTransactions()
assertThat(fragment.dialog).isNull()
}
// Assumes that the dialog had a button
// containing the text "Cancel".
onView(withText("Cancel")).check(doesNotExist())
}
}
}
I need some way to test the behavior of a DialogFragment's button and see that it dismisses itself and starts the second DialogFragment.
When I test for the button being clicked, the first DialogFragment is correctly dismissed, but the second DialogFragment is not launched. I've used both Espresso and UiAutomator and the click does occur, but reading the code snippet's explanation for testing DialogFragments it says,
"Even though dialogs are instances of graphical fragments, you use the launchFragment() method so that the dialog's elements are populated in the dialog itself, rather than in the activity that launches the dialog".
Is the reason that I am unable to check if the second DialogFragment exists or not, because it is an instance of a graphical fragment and my click listener for the button on the first DialogFragment cannot implement launchFragment() for the second DialogFragment?

Why are the height and width of the content View zero in Robolectric?

Here's a failing test:
#RunWith(RobolectricTestRunner.class)
public class FailTest {
#Test
public void heightAndWidth_shouldNotBeZero() {
TestActivity testActivity = Robolectric.buildActivity(TestActivity.class).create().resume().visible().get();
View contentView = testActivity.findViewById(69);
Assertions.assertThat(contentView.getWidth()).isNotZero();
Assertions.assertThat(contentView.getHeight()).isNotZero();
}
private static class TestActivity extends Activity {
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout contentView = new LinearLayout(this);
contentView.setId(69);
contentView.setLayoutParams(new LayoutParams(666, 666));
setContentView(contentView);
}
}
}
As you can see, I'm calling the visible() method on the ActivityController and driving the Activity lifecycle the correct way. Quoting the documentation:
Wait, What's This visible() Nonsense?
Turns out that in a real Android app, the view hierarchy of an
Activity is not attached to the Window until sometime after onCreate()
is called. Until this happens, the Activity's views do not report as
visible. This means you can't click on them (amongst other unexpected
behavior). The Activity's hierarchy is attached to the Window on a
device or emulator after onPostResume() on the Activity. Rather than
make assumptions about when the visibility should be updated,
Robolectric puts the power in the developer's hands when writing
tests.
So when do you call it? Whenever you're interacting with the views
inside the Activity. Methods like Robolectric.clickOn() require that
the view is visible and properly attached in order to function. You
should call visible() after create().
It seems as though I'm doing all I need to do. So why am I getting no height/width?
There is no layout pass in Robolectric, hence the view dimensions are always zero.
https://github.com/robolectric/robolectric/issues/819

getText from one layout and (setting it) setText in an other layout

i call this method SolveUpdation (from button- onclickAction Listener) from mainAcitivity with main layout. i use other layout to get value from user and set it as button title in the main layout and that is only instruction that does not works for me
private void SolveUpdation() { //this function call is generated from the main Activity with main layout
setContentView(R.layout.updateappliance); //this is 2nd layout to get values from user and use them as buttonText in the main layout
btnSaveApp = (Button) findViewById(R.id.Bupdatenow);
btnSaveApp.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
mOutEditText = (EditText) findViewById(R.id.edit_text_1);
TextView view1 = (TextView) findViewById(R.id.edit_text_1);
final String TitleApp1 = view1.getText().toString(); //the value is read properly here
// if (App1.length() > 0) {
// byte[] send = App1.getBytes();
// }
btnSaveApp.setText(TitleApp1); //this works fine
startActivity(new Intent(HomeScreen.this, HomeScreen.class));//this the main activity for main layout
setContentView(R.layout.main); //this is the main layout and this instruction works
buttonLED1.setText(TitleApp1); //buttonLED1 (a Togglebutton or can be simple) is defined in main layout and this does not works and this is what i am stuck with
SaveAppNamesToast(TitleApp1); //this is just to toast the value and it works fine.
}});
So plz can any one guide me why this instruction buttonLED1.setText(TitleApp1); does not works ??? Any help will be appreciatable.. thanks
No offense, but the way you write your code is not a good practice.
My advise: Stop calling another setContentView in your Main Activity. You should rather implement all needed Buttons and EditTexts in one layout and set their visiblity to gone or visible depending on which button was clicked.
If you don't wanna do this you should create a second class that handles the input of the user. After pressing the save button you initialize your intent for the main activity and give it via intent.putExtra("KEY", value) the input of the user.
Your Main Activity can receive this value via getIntent().getExtras().getInt("KEY").
By the way: I think your current code doesn't work because of the new Activity you start. Through this everything gets initialized again so the buttonLED1 that you see isn't the same buttonLED1 that gets the text.

Can anybody explain me this code?

import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class SlideImage extends MIDlet{
private Display display;
public void startApp(){
display = Display.getDisplay(this);
display.setCurrent(new IconsCanvas());
}
public void pauseApp(){}
public void destroyApp(boolean unconditional){
notifyDestroyed();
}
}
class IconsCanvas extends Canvas implements Runnable{
SlideMenu menu = null;
public IconsCanvas(){
Image[] image = new Image[10];
try{
image[0] = Image.createImage("/bollywood-height.png");
image[1] = Image.createImage("/212229_1193669628.png");
image[2] = Image.createImage("/95936_50.png");
image[3] = Image.createImage("/shreya.png");
image[4] = Image.createImage("/Aishw.png");
image[5] = Image.createImage("/karishma.png");
image[6] = Image.createImage("/tmb_jiahkhannishabd.png");
image[7] = Image.createImage("/amisha.png");
image[8] = Image.createImage("/shilpashetty.png");
image[9] = Image.createImage("/priti.png");
menu = new SlideMenu(new String[]{"1", "2", "3", "4",
"5", "6", "7", "8", "9", "10"},
image, getWidth(), getHeight());
new Thread(this).start();
}catch(Exception e){
e.printStackTrace();
}
}
protected void paint(Graphics g){
menu.paint(g);
}
public void keyPressed(int key){
int gameKey = getGameAction(key);
if(gameKey == Canvas.RIGHT){
menu.slideItem(1);
}else if(gameKey == Canvas.LEFT){
menu.slideItem(- 1);
}
}
public void run(){
try{
while(true){
repaint();
synchronized(this){
wait(100L);
}
}
}catch(Exception e){
e.printStackTrace();
}
}
}
Most of things in this code i got the reason for usage..but the rest of things like
SlideMenu,
menu.paint(g),
menu.slideItem(1);
menu.slideItem(-1);
The above things, i find difficult to know why they have been used...
It (your original snippet, the run method) looks like a thread whose sole task it is to just repaint the component every tenth of a second.
As to what component it refers to, you haven't provided enough information. It depends on the object that the run() is running for.
In terms of the synchronized bit, this is most likely a way to prevent other threads doing stuff to the component while this thread is within the sleep.
If this is the object xyz, then any other thread trying to execute a block like:
synchronized (xyz) {
// Work your magic here.
}
will not be able to run while the wait is progressing.
By the way, if you use four spaces at the start of each code line (instead of <pre>), you get the nice syntax colouring as well. If you just mark the entire bit of code in the editor and use CTRLK, it will do it for you automagicaly.
And, in terms of your update, SlideMenu (picture on this page) appears to be a menu where one item is shown on the screen and left/right arrows allow you to scroll:
+---------+
| |
/ | | \
< | image | >
\ | | /
| |
+---------+
(forgive my pitiful graphic ability, I'll leave it there in case the link below ever disappears).
No doubt the images in the IconsCanvas ate the menu items to display. With that in mind, the other things make sense.
SlideMenu, I've already described.
menu.paint(g) is called to display the new menu in response to the IconsCanvas getting a paint request.
menu.SlideItem() slides the menu left or right depending on the argument.
The 100ms makes more sense now, if the image actually scrolls smoothly to the left or right.
In the code snippet above, on the synchronized block, the author's intention is just to wait/sleep so to be cooperative and let other threads run, and wait() must always be synchronized. But there is no need to queue so many repaints as there is no true animation going on, just displaying static slides (Images) when advancing to next/prev; the Canvas won't get invalidated until a new slide is shown (or a call comes in, etc), meaning it should be Ok to only repaint when a new slide is shown. Note that if "smooth scrolling" is desired, such effect should be implemented by SlideMenu itself which must also take care of repaints() scheduling (vs. IconCanvas)
Other comments:
On SlideMenu -- need to see the implementation of it
On menu.paint(g) -- it is delegating to the slide menu itself to paint/ refresh the current slide
On menu.slideItem(1); / menu.slideItem(-1); -- without looking at SlideMenu it seems to be a mechanism for navigation next/previous
You should consider making IconCanvas and SlideMenu Singletons.

MFC menu item checkbox behavior

I'm trying to add a menu item such that it acts like a check mark where the user can check/uncheck, and the other classes can see that menu item's check mark status. I received a suggestion of creating a class for the menu option (with a popup option), however, I can't create a class for the menu option when I'm in the resource layout editor in Visual Studio 2005. It would be great to hear suggestions on the easiest way to create menu items that can do what I have described.
You should use the CCmdUI::SetCheck function to add a checkbox to a menu item, via an ON_UPDATE_COMMAND_UI handler function, and the ON_COMMAND handler to change the state of the checkbox. This method works for both for your application's main menu and for any popup menus you might create.
Assuming you have an MDI or SDI MFC application, you should first decide where you want to add the handler functions, for example in the application, main frame, document, or view class. This depends on what the flag will be used for: if it controls application-wide behaviour, put it in the application class; if it controls view-specific behaviour, put it in your view class, etc.
(Also, I'd recommend leaving the menu item's Checked property in the resource editor set to False.)
Here's an example using a view class to control the checkbox state of the ID_MY_COMMAND menu item:
// MyView.h
class CMyView : public CView
{
private:
BOOL m_Flag;
afx_msg void OnMyCommand();
afx_msg void OnUpdateMyCommand(CCmdUI* pCmdUI);
DECLARE_MESSAGE_MAP()
};
// MyView.cpp
BEGIN_MESSAGE_MAP(CMyView, CView)
ON_COMMAND(ID_MY_COMMAND, OnMyCommand)
ON_UPDATE_COMMAND_UI(ID_MY_COMMAND, OnUpdateMyCommand)
END_MESSAGE_MAP()
void CMyView::OnMyCommand()
{
m_Flag = !m_Flag; // Toggle the flag
// Use the new flag value.
}
void CMyView::OnUpdateMyCommand(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_Flag);
}
You should ensure the m_Flag member variable is initialised, for example, in the CMyView constructor or OnInitialUpdate function.
I hope this helps!
#ChrisN's approach doesn't quite work for MFC Dialog applications (the pCmdUI->SetCheck(m_Flag); has no effect). Here is a solution for Dialog apps:
// MyView.h
class CMyView : public CView
{
private:
BOOL m_Flag;
CMenu * m_menu;
virtual BOOL OnInitDialog();
afx_msg void OnMyCommand();
DECLARE_MESSAGE_MAP()
};
// MyView.cpp
BEGIN_MESSAGE_MAP(CMyView, CView)
ON_COMMAND(ID_MY_COMMAND, OnMyCommand)
END_MESSAGE_MAP()
BOOL CMyView::OnInitDialog()
{
m_menu = GetMenu();
}
void CMyView::OnMyCommand()
{
m_Flag = !m_Flag; // Toggle the flag
if (m_flag) {
m_menu->CheckMenuItem(ID_MENUITEM, MF_CHECKED | MF_BYCOMMAND);
} else {
m_menu->CheckMenuItem(ID_MENUITEM, MF_UNCHECKED | MF_BYCOMMAND);
}
}
References:
http://www.codeguru.com/forum/showthread.php?t=322261
I ended up retrieving the menu from the mainframe using GetMenu() method, and then used that menu object and ID numbers to call CheckMenuItem() with the right flags, as well as GetMenuState() function.

Resources