Strange problem with ViewFlipper - android

I have a ViewFlipper that shows 2 imageview (red one when disconnected and the green other when connected), however, i have a strange result: sometimes the red image is showen when i'm connected, it switches like this : red-green-and returns red(even when i'm connected).
Here is the JAVA code:
public void onRegistrationDone(String localProfileUri, long expiryTime) {
updateStatus("Enregistré au serveur.");
Log.d("SUCCEED","Registration DONE");
final ViewFlipper flipper = (ViewFlipper)findViewById(R.id.flipper);
flipper.postDelayed(new Runnable() {
public void run() {
flipper.showNext();
}
},2000);}
The view is initiated with the red image, then, when connected(and after 2 seconds) the next image is normally showen.
What could be the problem?
Thank you very much.
EDIT: XML file (Handler)
<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/sipLabel"
android:textSize="20sp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<ImageView android:id="#+id/status" android:layout_below="#id/sipLabel"
android:layout_width="fill_parent" android:scaleType="center"
android:layout_height="fill_parent" android:layout_weight="0.35" android:gravity="center"
/>
</LinearLayout>

I would do that differently. If that is just a matter of displaying different image (red/green) I would use ImageView UI control to display that image. And for the delayed display update you may use Handler. Something like this:
public void onRegistrationDone(String localProfileUri, long expiryTime)
{
updateStatus("Enregistré au serveur.");
Log.d("SUCCEED","Registration DONE");
mRegistered = true;
mRegistrationUpdateHandler.removeCallbacks(handleUpdateStatus);
mRegistrationUpdateHandler.postDelayed(handleUpdateStatus, 2000);
}
public void onRegistrationLost()
{
mRegistered = false;
mRegistrationUpdateHandler.removeCallbacks(handleUpdateStatus);
mRegistrationUpdateHandler.postDelayed(handleUpdateStatus, 2000);
}
private Runnable handleUpdateStatus = new Runnable()
{
public void run()
{
ImageView statusImageDisplay = (ImageView)findViewById(R.id.statusImage);
if (mRegistered)
{
statusImageDisplay.setImageDrawable(getResources().getDrawable(R.drawable.imageGreen));
else
{
statusImageDisplay.setImageDrawable(getResources().getDrawable(R.drawable.imageRed));
}
}
};

Related

Thread in Fragment only called once

I am trying to implement a thread that changes something on the UI in a Fragment. Therefore I need to refer to the main thread.
Based on my research, I've found that the following code should do the trick:
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Toast.makeText(menuActivity, "HELLO", Toast.LENGTH_SHORT).show();
}
});
This will execute only once though, even if the Looper should normally keep the thread alive. Trying to invoke Looper.prepare() inside the Handler will cause a RuntimeException as only one Looper is allowed per thread.
Edit: My goal is to update a TextView permanently each second.
I have also tried the following:
Thread t = new Thread() {
#Override
public void run() {
menuActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
System.out.println("-----------TEST");
}
});
}
};
t.start();
But this will execute only once too.
I've also read this article, but I guess my first snippet of code is just a shorter version of the code shown in the article.
Where may my mistake be in any of these snippets of code?
This question is not a duplicate, due to the fact that I presented a totally different snippet of code which is the base of the problem I had. Furthermore, the Looper is explained more in depth in this thread.
I understand that you want to update a text view repeatedly after 1 seconds. Here is a simple demo I just write.
Mockup screen
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/text_view_money"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:textColor="#android:color/black"
android:textSize="20sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="30dp"
android:layout_marginTop="30dp"
android:orientation="horizontal">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="startUpdateTextViewMoney"
android:text="Start" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="stopUpdateTextViewMoney"
android:text="Stop" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<EditText
android:id="#+id/edit_text_money"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="setMoney"
android:text="SET MONEY" />
</LinearLayout>
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final int UPDATE_TEXT_MONEY_INTERVAL = 1000;
private Handler mMainHandler;
private TextView mTextViewMoney;
private TextView mEditTextMoney;
private String money;
private Runnable mUpdateTextViewMoneyTask = new Runnable() {
#Override
public void run() {
if (TextUtils.isEmpty(money)) {
mTextViewMoney.setText(String.valueOf(SystemClock.elapsedRealtime()));
} else {
mTextViewMoney.setText(money);
money = null;
}
mMainHandler.postDelayed(this, UPDATE_TEXT_MONEY_INTERVAL);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextViewMoney = findViewById(R.id.text_view_money);
mEditTextMoney = findViewById(R.id.edit_text_money);
mMainHandler = new Handler(Looper.getMainLooper());
}
#Override
protected void onStop() {
super.onStop();
stopUpdateTextViewMoney(null);
}
public void startUpdateTextViewMoney(View view) {
mMainHandler.post(mUpdateTextViewMoneyTask);
}
public void stopUpdateTextViewMoney(View view) {
mMainHandler.removeCallbacks(mUpdateTextViewMoneyTask);
}
public void setMoney(View view) {
String money = mEditTextMoney.getText().toString();
this.money = !TextUtils.isEmpty(money) ? money : "";
}
}
When users press Start button, the app will start updating text view each second
When users press Stop button, the app will stop updating the text view.
If users want to set a new money to display in the next time, just enter in the edit text then press Set Money.
This will execute only once though, even if the Looper should normally
keep the thread alive.
You seem to be confused about the Looper's purpose/functionality. The Looper is keeping the thread alive. If the main thread was not kept alive, your application would exit. The Looper does not, however, provide repeated execution of the Runnables posted to the Handler/Thread which it is associated with. Each Runnable is executed exactly once. If you want to execute the same Runnable multiple times, you must post it multiple times. For example:
Handler mainThreadHandler = new Handler(Looper.getMainLooper());
Runnable doToast = new Runnable() {
#Override
public void run() {
Toast.makeText(menuActivity, "HELLO", Toast.LENGTH_SHORT).show();
}
});
mainThreadHandler.post(doToast); // Queue the first execution of the code in the Runnable's run() method.
mainThreadHandler.post(doToast); // Queue the second execution of the code in the Runnable's run() method.

Android Splash Screen Animation (Left to Right)

Currently, I am trying to create splash screen with this animation:
Progress Bar Effect
From the start, I thought of creating the progress bar, however, I can't make it and unable to find exact design. Thus, I was planning using animation method but most of the tutorial are fade in/our or move the item from left to right. Any idea how to create this kind of animation in splash screen (3 second)?
You can make this manually using handler to make the images appear after period of time.
At first you will create a layout containing these images and make them invisible, then in the handler show them one by one.
here's how to do it.
this is in layout:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:orientation="horizontal">
<ImageView
android:id="#+id/img1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:src="#android:drawable/presence_online"
android:visibility="invisible" />
<ImageView
android:id="#+id/img2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:src="#android:drawable/presence_online"
android:visibility="invisible" />
<ImageView
android:id="#+id/img3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:src="#android:drawable/presence_online"
android:visibility="invisible" />
<ImageView
android:id="#+id/img4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:src="#android:drawable/presence_online"
android:visibility="invisible" />
</LinearLayout>
and this in java class:
final int TIME_OUT = 1000;
final ImageView imageView1 = (ImageView) findViewById(R.id.img1);
final ImageView imageView2 = (ImageView) findViewById(R.id.img2);
final ImageView imageView3 = (ImageView) findViewById(R.id.img3);
final ImageView imageView4 = (ImageView) findViewById(R.id.img4);
new Handler().postDelayed(new Runnable() {
// This method will be executed once the timer is over
#Override
public void run() {
imageView1.setVisibility(View.VISIBLE);
}
}, TIME_OUT);
new Handler().postDelayed(new Runnable() {
// This method will be executed once the timer is over
#Override
public void run() {
imageView2.setVisibility(View.VISIBLE);
}
}, TIME_OUT * 2);
new Handler().postDelayed(new Runnable() {
// This method will be executed once the timer is over
#Override
public void run() {
imageView3.setVisibility(View.VISIBLE);
}
}, TIME_OUT * 3);
new Handler().postDelayed(new Runnable() {
// This method will be executed once the timer is over
#Override
public void run() {
imageView4.setVisibility(View.VISIBLE);
}
}, TIME_OUT * 4);
you can change the TIME_OUT as it suits you and so the android:src.
i tried this and works well.
if there's anything not clear let me know.
For the ProgressBar effect as indicator of progress, please look at the reference here. Also take a look at thread of suggestions as well as the selected answer here - they show how to do a progress bar animation. You can also look at the selected answer here about making the progress bar to update smoothly. I hope this points you in the right direction.

Creating Real-Time Graphs in Android App for Bluetooth Pulse Rate Sensor

I'm currently developing an Android Application which connects via Bluetooth Low Energy to an Arduino which has the nRF8001 Bluetooth Low Energy Module with a connect the SEN-11574 Pulse Rate Sensor available at Spark Fun ( https://www.sparkfun.com/products/11574 ).
I have been trying to implement a graph which plots the data on the graph every time I tap on 'Get Heart Rate' button but I'm only managing the following:
I've researched a number of different resources which include the following yet unfortunately they don't answer my question:
1,2,3,4,5,6,7
I am using the Android Graph View Library to try and solve my problem as it offers the best integration with Android Studio.
I am struggling with three main things:
Labelling the X and Y-Values properly
Appending the Heart Rate Sensor Data to the Graph
The full project is available at : Arduino Pulse Rate
I seem to be struggling the most with these two sections of code:
private void writeSensorData(final CharSequence text) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Log.e(LOG_TAG,text.toString());
output=text.toString().trim();
if (output.length() > 0 && output.length() <=3) {
pulseRateView.setText(output);
rateSeries.appendData(new GraphView.GraphViewData(graph2LastXValue,Double.parseDouble(output)),AutoScrollX,maxDataCount);
}
else {
return;
}
}
});
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pulse);
//Connect U.I Elements
getPulseRate = (Button)findViewById(R.id.heartRateBtn);
pulseRateView = (TextView) findViewById(R.id.pulseValueView);
connectionStsView = (TextView) findViewById(R.id.connectionStsView);
refreshButton = (Button) findViewById(R.id.refreshBtn);
// init heart rate series data
rateSeries = new GraphViewSeries(new GraphView.GraphViewData[] {
});
GraphView graphView = new LineGraphView(this, "Pulse Rate Sensor");
graphView.addSeries(rateSeries);
graphView.setScrollable(true);
graphView.setScalable(true);
LinearLayout layout = (LinearLayout) findViewById(R.id.graph1);
layout.addView(graphView);
getPulseRate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String setOutputMessage = "/bpm /";
tx.setValue(setOutputMessage.getBytes(Charset.forName("UTF-8")));
if (gatt.writeCharacteristic(tx)) {
writeConnectionData("Sent: " + setOutputMessage);
} else {
writeConnectionData("Couldn't write TX characteristic!");
}
}
});
refreshButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
restartScan();
}
});
}
Would appreciate any help and thank you for your time.
The solution below configures your graph to achieve the basic layout and functionality you want. Note that I have bound a sample graph update to the clicking of the refresh button - you can bind a similar procedure to your interface with the actual pulse device. All you need is the time-bpm pair to be plotted to the x and y axes, respectively.
PulseActivity#onCreate
// Local variable for simulating the sample time
private int x = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pulse);
//Connect U.I Elements
getPulseRate = (Button) findViewById(R.id.heartRateBtn);
pulseRateView = (TextView) findViewById(R.id.pulseValueView);
connectionStsView = (TextView) findViewById(R.id.connectionStsView);
refreshButton = (Button) findViewById(R.id.refreshBtn);
final GraphView graphView = new LineGraphView(
this, // context
"Pulse Rate Sensor" // heading
);
graphView.setVerticalLabels(new String[]{"high", "normal", "low"});
graphView.setCustomLabelFormatter(new CustomLabelFormatter() {
#Override
public String formatLabel(double value, boolean isValueX) {
if (isValueX) {
return null;
} else {
if (value < 60) {
return "low";
} else if (value < 100) {
return "normal";
} else {
return "high";
}
}
}
});
// init heart rate series data
rateSeries = new GraphViewSeries(new GraphView.GraphViewData[]{
});
graphView.addSeries(rateSeries);
LinearLayout layout = (LinearLayout) findViewById(R.id.graph1);
layout.addView(graphView);
getPulseRate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String setOutputMessage = "/bpm /";
tx.setValue(setOutputMessage.getBytes(Charset.forName("UTF-8")));
if (gatt.writeCharacteristic(tx)) {
writeConnectionData("Sent: " + setOutputMessage);
} else {
writeConnectionData("Couldn't write TX characteristic!");
}
}
});
refreshButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//restartScan();
rateSeries.appendData(new GraphView.GraphViewData(x += 3, new Random().nextInt(100)), false, 100);
graphView.redrawAll();
}
});
}
activity_pulse.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">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="250dip"
android:id="#+id/graph1"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp" />
<LinearLayout
android:id="#+id/rest"
android:layout_width="fill_parent"
android:layout_height="250dip"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Refresh Connection"
android:id="#+id/refreshBtn"
android:layout_gravity="center_horizontal" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Get Heart Rate"
android:id="#+id/heartRateBtn"
android:layout_gravity="center_horizontal" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Last Pulse Rate Value"
android:id="#+id/pulsePlaceholderText"
android:layout_gravity="center_horizontal" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="#+id/pulseValueView"
android:layout_gravity="center_horizontal" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Connection Status"
android:id="#+id/connectionStsView"
android:layout_gravity="center_horizontal" />
</LinearLayout>
</LinearLayout>

Android when screen dims add a layer above everything to consume the onclick

In my app I want when the screen dims to add a layer above everything so when the users taps on screen the dimness will be gone and then he can use the app. If I dont do this when the screen is dimmed and the user taps on screen he will activate something in the app.
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<!-- The main content view -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/radio_frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</FrameLayout>
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</FrameLayout>
</LinearLayout>
<LinearLayout
android:id="#+id/disc"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffff"
android:gravity="center"
android:visibility="gone"
android:orientation="vertical" />
<!-- The navigation drawer -->
<ListView
android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#ffffff"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="10dp" />
this is my layout. When the screen dims i make the disc visible and when the user touches something on screen I make it View.gone. The problem is that the click on the disc is also activating something on my content frame fragment.
Is there a way to make it now happen? I want the click to activate only the disc onclickhandler not anything else. Or is there any other way to do this?
So I figured out how to do this. The trick is to have an onclickListener on the view itself. I was just making it disappear while I had to also get the click.
private final Runnable disconnectCallback = new Runnable() {
#Override
public void run() {
runOnUiThread(new Thread(new Runnable() {
#Override
public void run() {
disconnect.setVisibility(View.VISIBLE);
}
}));
}
};
private static final Handler disconnectHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
}
};
public void resetDisconnectTimer() {
disconnectHandler.removeCallbacks(disconnectCallback);
disconnectHandler.postDelayed(disconnectCallback, 3000);
}
public void stopDisconnectTimer() {
disconnectHandler.removeCallbacks(disconnectCallback);
}
#Override
public void onUserInteraction() {
resetDisconnectTimer();
}
#Override
public void onResume() {
super.onResume();
resetDisconnectTimer();
}
and in onCreate i have this
disconnect = findViewById(R.id.disc);
disconnect.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
disconnect.setVisibility(View.GONE);
}
});
in my previous attempt i was making the disconnect "gone" inside the handler. Now i have an onclick listener on this.

Layout issue while loading an image on Galaxy Tab 2

Loading an image that is larger than the width of a Galaxy Tab 2 P5100 (running 4.1.2) into an ImageView adds some sort of top/bottom padding to the loaded image.
Here's a screenshot with Show layout boundaries turned on:
Here's how it should look (from a Nexus 10 running 4.4.2):
The code I use (for both examples above) is
public class ImageBugActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bug);
// This bug is still reproducible if I use the
// Universal-Image-Loader library or if I change the dimensions of
// the image to a different width
loadImage("http://placehold.it/1600x1000", (ImageView)findViewById(R.id.image));
}
private void loadImage(final String url, final ImageView view) {
new Thread(new Runnable() {
#Override
public void run() {
try {
final Bitmap bitmap = BitmapFactory.decodeStream(new URL(url).openConnection().getInputStream());
runOnUiThread(new Runnable() {
#Override
public void run() {
view.setImageBitmap(bitmap);
}
});
} catch (Exception e) {
Log.e("loadImage", e.getMessage(), e);
}
}
}).start();
}
}
And the layout file is
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="On a Galaxy Tab 2 the image below it is pushed to the center of the remaining space." />
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top" />
</LinearLayout>
Does this seem to be an Android/Samsung bug or am I making a dumb mistake?
Setting the android:scaleType of the ImageView to "fitStart" should do the trick.
You should use "match_parent" for layout_height of the ImageView.
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="top" />

Categories

Resources