I have defined preferences in my app using preferences.xml and a PreferenceActivity. The settings are presented in the phone in a ScrollView-like-way. I would like to always show the vertical scrollbars all the time. In Android 1.6 they do not fade away, but in Android 2.2 the fade away after about a second. In a ScrollView I can control this using android:scrollbarAlwaysDrawVerticalTrack or android:scrollbarDefaultDelayBeforeFade. How can I do this with the preference widget?
/P
This worked for my Android 2.3.3 .
public class MyPreferenceActivity extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getListView().setScrollbarFadingEnabled(false);
...
}
...
}
Try this as the above suggestions didn't work for me when I wanted to do this for a TextView:
TextView.setScrollbarFadingEnabled(false);
Try android:scrollbarAlwaysDrawVerticalTrack="true" in the PreferenceScreen.
So hey, this is a seriously ugly solution, but its short and it works.
public class PreferenceActivity extends Activity {
//Sorry for stupid variable names, couldn't be bothered to be smart
private ScrollView svOptions;
private Runnable _run_sb_on;
private final Handler _handle_sb_on = new Handler();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.preference);
svOptions = (ScrollView) findViewById(R.id.svOptions);
_run_sb_on = new Runnable() { //i hate you google for making me write crap code !
public void run() {
svOptions.fling(0); //don't move it, just keep it alive
_handle_sb_on.postDelayed(this, 300); //300 is the timeout of the fader
}
};
_handle_sb_on.post(_run_sb_on);
}
// etc
}
So there you have it. Note that the fling can eat on-touch events, its rare but its a little annoying - but workable.
Put this in the scroller that you want to show scrollbars all the time:
android:scrollbarFadeDuration="0"
Counterintuitive, I know, but it works perfectly.
Related
My problem is exactly like this link but it's not in android.
I have one button on a layout and two buttons on an another one. On my application, ClickScreen activity can be triggered by either FirstCase activity or SecondCase activity.
I tried to make a conditional statement on my ClickScreen for which activity is triggered but couldn't handle it. I don't want to create two more classes to do this since it's not an efficient technique.
private void goTo2ndPage() {
Intent i3 = new Intent(this, ClickScreen.class);
startActivity(i3);
}
public class ClickScreen extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.click_screen);
}
}
As we discussed in comments. It looks like what you really want is to add extra data in your intent so that Started Activity can get it and act accordingly.
Check out this post !
I am trying to Print some messages using Log.i but it doesn't print anything, the problem starts after I updated the Android studio.
How can I solve the problem?
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("check","**************checking");
setContentView(R.layout.activity_main);
}
}
An alternate solution, but it's not the best.
System.out.print();
Make sure you select the device you are using, you can do it on the top left side of the Logcat.
for example if you used an emulator and than a device make sure the device is selected.
Try using the tag constant
public static final string TAG = "MainActivity"
Then do
Log.d(TAG, YOURMESSAGE)
Also as an alternative you can use System.out
Is there any way to call a listener manually from code?
More background information: I use a Spinner and a DatePicker. With the Spinner you can choose a reason for staying at home (maybe your ill, maybe you have vacation) and with the DatePicker you can choose the date how long you will not be available. With these two pieces of information I build up a string for a TextView and show the same data in a compact way. The building process for the string is set by some listeners which recognize changes on one of the two controls and build and set up the new string.
If I start the program and read some data from a server the string will not be build (clearly because nothing changed and no listener will called).
The workaround is to build the string in my own onLoaddata() method. But I think it would be smoother way to call one listener to build the string for me. I also can "call" a listener if I just do some fake .updateDate but I don't think it’s a good idea to create useless calls...
Maybe someone of you have a good hint for me?
Use the following pattern:
public class YourActivity extends Activity implements OnClickListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
// Some initialization here
findViewById(R.id.some_button).setOnClickListener(this);
...
// Here you want to update your view
updateTextView();
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.some_button:
// Here you also want to update your view
updateTextView();
break;
...
}
}
private void updateTextView() {
// Here you update your view
...
}
}
I'm trying to write a simple test app to run in JUnit. I've been having trouble getting clickView to click on the proper view. Below is some sample code that can be used on SkeletonActivity sample app that comes with the SDK.
public class SkeletonInstrumentation extends ActivityInstrumentationTestCase2<Activity>{
private Activity act;
private Button bClear;
private Button bBack;
private EditText eMain;
public SkeletonInstrumentation(){
super("com.example.android.skeletonapp", Activity.class);
}
public void setUp() {
String app = this.getInstrumentation().getTargetContext().getPackageName();
this.setActivityInitialTouchMode(true);
act = this.launchActivity(app, SkeletonActivity.class, Bundle.EMPTY);
bClear = (Button) act.findViewById(R.id.clear);
bBack = (Button) act.findViewById(R.id.back);
eMain = (EditText) act.findViewById(R.id.editor);
}
public void testClick()
{
TouchUtils.clickView(this, bClear);
}
public void testSendKeys()
{
act.runOnUiThread(
new Runnable(){
public void run(){
bClear.clearFocus();
eMain.requestFocus();
}
}
);
this.sendKeys("A B C D E F G ENTER");
}
}
testClick runs, but clicks on the main EditText view that has focus when the Activity starts and ends up bringing up the on-screen keyboard. I want it to click on the 'Clear' button below the EditText. Can someone tell me what's wrong here?
Adding the min and max target SDK in the AndroidManifest.xml worked for me; I got the idea from this answer. In the project that is being tested (not the test project) I added the following line to AndroidManifest.xml:
<uses-sdk android:targetSdkVersion="17" android:minSdkVersion="17"/>
and all of my uses of TouchUtils started behaving consistently again.
I had the same problem in this question and while I was able to find a workaround but it became really cumbersome so I spent more hours getting to the bottom of it.
The use of clickView here is correct. The problem was in the AndroidManifest.xml. Min and Target SDK must be set for it to work properly.
I've been working with AsyncTasks in Android and I am dealing with an issue.
Take a simple example, an Activity with one AsyncTask. The task on the background does not do anything spectacular, it just sleeps for 8 seconds.
At the end of the AsyncTask in the onPostExecute() method I am just setting a button visibility status to View.VISIBLE, only to verify my results.
Now, this works great until the user decides to change his phones orientation while the AsyncTask is working (within the 8 second sleep window).
I understand the Android activity life cycle and I know the activity gets destroyed and recreated.
This is where the problem comes in. The AsyncTask is referring to a button and apparently holds a reference to the context that started the AsyncTask in the first place.
I would expect, that this old context (since the user caused an orientation change) to either become null and the AsyncTask to throw an NPE for the reference to the button it is trying to make visible.
Instead, no NPE is thrown, the AsyncTask thinks that the button reference is not null, sets it to visible. The result? Nothing is happening on the screen!
Update: I have tackled this by keeping a WeakReference to the activity and switching when a configuration change happens. This is cumbersome.
Here's the code:
public class Main extends Activity {
private Button mButton = null;
private Button mTestButton = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mButton = (Button) findViewById(R.id.btnStart);
mButton.setOnClickListener(new OnClickListener () {
#Override
public void onClick(View v) {
new taskDoSomething().execute(0l);
}
});
mTestButton = (Button) findViewById(R.id.btnTest);
}
private class TaskDoSomething extends AsyncTask<Long, Integer, Integer>
{
#Override
protected Integer doInBackground(Long... params) {
Log.i("LOGGER", "Starting...");
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 0;
}
#Override
protected void onPostExecute(Integer result) {
Log.i("LOGGER", "...Done");
mTestButton.setVisibility(View.VISIBLE);
}
}
}
Try executing it and while the AsyncTask is working change your phones orientation.
AsyncTask is not designed to be reused once an Activity has been torn down and restarted. The internal Handler object becomes stale, just like you stated. In the Shelves example by Romain Guy, he simple cancels any currently running AsyncTask's and then restarts new ones post-orientation change.
It is possible to hand off your Thread to the new Activity, but it adds a lot of plumbing. There is no generally agreed on way to do this, but you can read about my method here : http://foo.jasonhudgins.com/2010/03/simple-progressbar-tutorial.html
If you only need a context and won't use it for ui stuff you can simply pass the ApplicationContext to your AsyncTask.You often need the context for system resources, for example.
Don't try to update the UI from an AsyncTask and try to avoid handling configuration changes yourself as it can get messy. In order to update the UI you could register a Broadcast receiver and send a Broadcast.
You should also have the AsyncTask as a separate public class from the activity as mentioned above, it makes testing a lot easier. Unfortunately Android programming often reinforces bad practices and the official examples are not helping.
This is the type of thing that leads me to always prevent my Activity from being destroyed/recreated on orientation change.
To do so add this to your <Activity> tag in your manifest file:
android:configChanges="orientation|keyboardHidden"
And override onConfigurationChanged in your Activity class:
#Override
public void onConfigurationChanged(final Configuration newConfig)
{
// Ignore orientation change to keep activity from restarting
super.onConfigurationChanged(newConfig);
}
To avoid this you can use the answer givin here: https://stackoverflow.com/a/2124731/327011
But if you need to destroy the activity (different layouts for portrait and landscape) you can make the AsyncTask a public class (Read here why it shouldn't be private Android: AsyncTask recommendations: private class or public class?) and then create a method setActivity to set the reference to the current activity whenever it is destroyed/created.
You can see an example here: Android AsyncTask in external class