Android Switch Issue - java

I am currently using a switch in my Android application as sort of options in my settings class. However, when I change the state of the switch, from say false to true, and go back to the menu, and then go back to the settings activity, the state of the switch goes back to the default value. Is there a key line that basically saves the switch's state so that when a user returns to it, the state is the same? I don't think this question requires code, but if you think it's helpful, please let me know and I'll attach it. Thanks!
here is my activity code:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.speedytext.Options" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Switch
android:id="#+id/switch1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView1"
android:layout_marginLeft="46dp"
android:layout_marginTop="48dp"
android:layout_toRightOf="#+id/textView1"
android:text="Switch" />
<Switch
android:id="#+id/switch2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="#+id/switch1"
android:layout_below="#+id/switch1"
android:layout_marginTop="66dp"
android:text="Switch" />
</RelativeLayout>
here is my java code:
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.Switch;
public class Options extends ActionBarActivity {
private static Switch ding;
private Switch countdown;
public static boolean isDingChecked;
public static boolean isCountdownChecked;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_options);
ding = (Switch) findViewById(R.id.switch1);
ding.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// do something, the isChecked will be
// true if the switch is in the On position
isDingChecked = isChecked;
System.out.println(isDingChecked);
System.out.println(isDingChecked());
}
});
countdown = (Switch) findViewById(R.id.switch2);
countdown.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// do something, the isChecked will be
// true if the switch is in the On position
isCountdownChecked = isChecked;
System.out.println(isCountDownChecked());
}
});
isDingChecked = ding.isChecked();
isCountdownChecked= countdown.isChecked();
}
public static boolean isDingChecked()
{
return isDingChecked;
}
public static boolean isCountDownChecked()
{
return isCountdownChecked;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.options, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}

In onCreate(), call setChecked() with your stored "is checked" value to set the default to whatever was stored previously.
Also, consider storing the settings to e.g. shared preferences. static variables do not persist over application relaunches and often make your code harder to maintain.

Shared Preference Class
public class AppPreferences {
private SharedPreferences appSharedPrefs;
private Editor prefsEditor;
public AppPreferences(Context context, String Preferncename) {
this.appSharedPrefs = context.getSharedPreferences(Preferncename,
Activity.MODE_PRIVATE);
this.prefsEditor = appSharedPrefs.edit();
}
/****
*
* getdata() get the value from the preference
*
* */
public String getData(String key) {
return appSharedPrefs.getString(key, "");
}
/****
*
* SaveData() save the value to the preference
*
* */
public void SaveData(String text, String Tag) {
prefsEditor.putString(Tag, text);
prefsEditor.commit();
}
public void clear()
{
prefsEditor.clear();
prefsEditor.commit();
}
}
Usage of Shared Preference in activity
AppPreferences appPref;
appPref = new AppPreferences(getApplicationContext(), "PREFS");
To save the state
When the state of the switch is changed save the state true or false to a tag in shared preference
You can use this line to save the state
appPref.SaveData("Value", "Tag");
so it will be like this for checked state appPref.SaveData("true", "state");
and appPref.SaveData("false", "state"); for unchecked state
in the oncreate of your activity get the value from the shared preference
using
appPref.getData("state");
if(appPref.getData("state").equals("true"))
{
//set ur switch button to checked state
}
else if(appPref.getData("state").equals("false"))
{
//set ur switch button to unchecked state
}
then check the result string for true or false
and set the switch accordingly

Related

Android EditText doesn't reappear at the same place

I'm working on a Credit / Debit card form on Android.
What I'm trying to achieve:
I have an EditText field called CardNumber where the user is supposed to type in his / her card number. Upon receiving all the digits of the card number, two additional EditText fields, ExpiryDate & CVV slide out. If the user erases any of the digits in the CardNumber field, bot the ExpiryDate & the CVV fields should disappear or slide in & remove the text written on them.
When the user types in the CardNumber again & enters all the digits required, both ExpiryDate & CVV should appear again in the same place they appeared before.
But this is what I'm getting
They are not appearing in the same place. How do I achieve this & how do I remove the text from both ExpiryDate & CVV upon their disappearance.
This is what I have done so far
MainActivity.java
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
import java.security.Key;
public class MainActivity extends AppCompatActivity {
private EditText cardNumber, expiryDate, CVV, nameOnCard;
private boolean flag = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);//Locks the screen orientation
init(); //Initializes the variables
typefunc();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void init()
{
cardNumber = (EditText) findViewById(R.id.cardNumber); //Field for storing the card number
expiryDate = (EditText) findViewById(R.id.expiryDate); //For storing the Expiry Date
CVV = (EditText) findViewById(R.id.CVV); //For storing the CVV
nameOnCard = (EditText) findViewById(R.id.nameOnCard); //For storing the name of the Cardholder
}
public void typefunc()
{
//FORMATTING CARD NUMBER FIELD
cardNumber.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
if(s.length()==19)
{
//MAKING EXPIRY DATE VISIBLE & PUTTING FOCUS ON IT
expiryDate.setVisibility(View.VISIBLE);
expiryDate.requestFocus();
//SLIDE OUT ANIMATION (FADE IN --> FADE OUT)
expiryDate.setAlpha(0.0f);//(INVISIBLE)
expiryDate.animate().translationY(expiryDate.getHeight()).alpha(1.0f);//(VISIBLE)
//MAKING CVV VISIBLE
CVV.setVisibility(View.VISIBLE);
//SLIDE OUT ANIMATION (FADE IN --> FADE OUT)
CVV.setAlpha(0.0f); //(INVISIBLE)
CVV.animate().translationY(CVV.getHeight()).alpha(1.0f); //(VISIBLE)
}
if(s.length()<19)
{
//DISAPPEARING THE EXPIRY DATE 7 CVV
expiryDate.setVisibility(View.GONE);
CVV.setVisibility(View.GONE);
//CLEARING THE FOCUS
expiryDate.clearFocus();
//SLIDE IN ANIMATION (FADE OUT --> FADE IN)
expiryDate.animate().translationY(0).alpha(0.0f);
CVV.animate().translationY(0).alpha(0.0f);
}
}
#Override
public void afterTextChanged(Editable s)
{
char space = ' ';
if(s.length()>0 && (s.length()%5) == 0)
{
char c = s.charAt(s.length()-1);
if(Character.isDigit(c))
{
s.insert(s.length()-1,String.valueOf(space));
}
}
}
});
//FORMATTING THE EXPIRY DATE FIELD
expiryDate.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
if(s.length()==5)
CVV.requestFocus();
}
#Override
public void afterTextChanged(Editable s)
{
char slash = '/';
if(s.length()>0 && (s.length()%3) == 0)
{
char c = s.charAt(s.length()-1);
if(Character.isDigit(c))
s.insert(s.length()-1,String.valueOf(slash));
}
}
});
CVV.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
if(s.length()==3) {
nameOnCard.setVisibility(View.VISIBLE);
}
}
#Override
public void afterTextChanged(Editable s)
{
if(s.length()==3)
nameOnCard.requestFocus();
}
});
}
}
content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="payment.ec.juspay.in.cardform.MainActivity"
tools:showIn="#layout/activity_main">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Credit / Debit"
android:id="#+id/cardformHeading"
android:layout_marginLeft="42dp"
android:layout_marginStart="30dp"
android:layout_marginTop="20dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<EditText
android:layout_width="300dp"
android:layout_height="wrap_content"
android:inputType="phone"
android:id="#+id/cardNumber"
android:maxLength="20"
android:hint="Card Number"
android:layout_below="#+id/cardformHeading"
android:layout_alignLeft="#+id/cardformHeading"
android:layout_alignStart="#+id/cardformHeading"
android:layout_marginTop="32dp"
android:singleLine="true"/>
<EditText
android:layout_width="200dp"
android:layout_height="wrap_content"
android:id="#+id/expiryDate"
android:hint="Expiry Date (mm/yy)"
android:maxLength="5"
android:inputType="phone"
android:layout_below="#+id/cardNumber"
android:layout_alignLeft="#+id/cardNumber"
android:layout_alignStart="#+id/cardNumber"
android:singleLine="true"
android:visibility="gone"/>
<EditText
android:layout_width="80dp"
android:layout_height="wrap_content"
android:inputType="numberPassword"
android:ems="10"
android:maxLength="3"
android:id="#+id/CVV"
android:hint="CVV"
android:layout_below="#+id/cardNumber"
android:layout_alignRight="#+id/cardNumber"
android:layout_alignEnd="#+id/cardNumber"
android:singleLine="true"
android:visibility="gone"/>
<EditText
android:layout_width="300dp"
android:layout_height="wrap_content"
android:id="#+id/nameOnCard"
android:hint="Name On Card"
android:layout_below="#+id/expiryDate"
android:layout_alignLeft="#+id/expiryDate"
android:layout_alignStart="#+id/expiryDate"
android:singleLine="true"
android:visibility="gone"/>
</RelativeLayout>
What am I missing?
Thank you for your time!!
You probably don't want to translate the EditText, because that's why it's placed lower on the screen than wanted.
If you anyways want to use a translate animation you have to use View.INVISIBLE instead of View.GONE, otherwise the initial getHeight() will return 0. You also need to translate to 0 for s.length()==19 and to -expiryDate.getHeight() for s.length()<19
if(s.length()==19)
{
//MAKING EXPIRY DATE VISIBLE & PUTTING FOCUS ON IT
expiryDate.setVisibility(View.VISIBLE);
expiryDate.requestFocus();
//SLIDE OUT ANIMATION (FADE IN --> FADE OUT)
expiryDate.setAlpha(0.0f);//(INVISIBLE)
expiryDate.animate().translationY(0).alpha(1.0f);//(VISIBLE)
//MAKING CVV VISIBLE
CVV.setVisibility(View.VISIBLE);
//SLIDE OUT ANIMATION (FADE IN --> FADE OUT)
CVV.setAlpha(0.0f); //(INVISIBLE)
CVV.animate().translationY(0).alpha(1.0f); //(VISIBLE)
}
else if(s.length()<19 && expiryDate.getVisibility() == View.VISIBLE)
{
//DISAPPEARING THE EXPIRY DATE 7 CVV
expiryDate.setVisibility(View.INVISIBLE);
CVV.setVisibility(View.INVISIBLE);
//CLEARING THE FOCUS
expiryDate.clearFocus();
//SLIDE IN ANIMATION (FADE OUT --> FADE IN)
expiryDate.animate().translationY(-expiryDate.getHeight()).alpha(0.0f);
CVV.animate().translationY(-CVV.getHeight()).alpha(0.0f);
}
Additionally you would want to translate the views up in your init method like this
expiryDate.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
expiryDate.animate().translationY(-expiryDate.getHeight());
expiryDate.getViewTreeObserver().removeOnPreDrawListener(this);
return true;
}
});
Try using View.INVISIBLE instead of View.GONE.
View.GONE This view is invisible, and it doesn't take any space for layout purposes.
View.INVISIBLE This view is invisible, but it still takes up space for
layout purposes.
Also update the view XMLs from android:visibility="gone" to android:visibility="invisible" and see if it works.
You are getting height from Editext.getHeight(). When the view is not drawn it returns zero. So Second time you get some xx value. So only second time your slideout animation will happen.
If slide out animation is not your preference use animatelayoutchanges= true for view group. It will animate some standard animations. That will better.
Or you can get height from onPredrawListener.
Thanks

OnClick Not Firing?

I'm new to android and having trouble getting some simple things going!
Here is some basic code:
MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Lets go ahead and set our buttons up.
ServerButton = (Button)this.findViewById(R.id.ServerButton);
ClientButton = (Button)this.findViewById(R.id.ClientButton);
BTServer = new BluetoothServerService(this, mHandler);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void ServerButtonClick(View v){
Log.d("BLUETOOTH MAIN ACTIVITY", "It got here");
BTServer.start();
}
private final Handler mHandler = new Handler(){
#Override
public void handleMessage(Message msg){
switch (msg.what){
case HANDLER_CHANGE_SERVER_STATUS:
switch(msg.arg1){
case SERVER_STATUS_OFF:
CURRENT_SERVER_STATUS = SERVER_STATUS_OFF;
//We should probably add some logging, and the change to the button
break;
case SERVER_STATUS_ON:
CURRENT_SERVER_STATUS = SERVER_STATUS_ON;
//Again lets add some logging, etc.
break;
case SERVER_STATUS_ON_CONNECTED:
CURRENT_SERVER_STATUS = SERVER_STATUS_ON_CONNECTED;
//Again lets add some logging, etc.
break;
}
}
return;
}
};
My XML Looks like this:
<Button
android:id="#+id/ServerButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="146dp"
android:layout_marginLeft="64dp"
android:text="Connect to Server" />
<Button
android:id="#+id/ClientButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="28dp"
android:text="Start Server"
android:onClick="ServerButtonClick"/>
In my logs, I see the logs saying it creates the BTServer object, but I can't get any logs to show up when I click the button.
Any suggestions?
Thanks!
define a click action for ClientButton inside onCreate method
ClientButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
}
});
also for ServerButton define a click action like the above as
ServerButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
}
});
For me, I find it's best to have your Activity implement android.view.View.OnClickListener, then set your Button's onClickListener to your Activity.
Here's an example Activity class:
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class Home extends Activity implements OnClickListener
{
#Override
public void onCreate (Bundle savedInstanceState)
{
super.onCreate (savedInstanceState);
setContentView (R.layout.activity_main);
Button serverButton = (Button)this.findViewById (R.id.ServerButton);
serverButton.setOnClickListener (this);
Button clientButton = (Button)this.findViewById (R.id.ClientButton);
clientButton.setOnClickListener (this);
}
#Override
public void onClick(View button)
{
int buttonId = button.getId ();
if (buttonId == R.id.ServerButton)
{
// Do server stuff.
}
if (buttonId == R.id.ClientButton)
{
// Do client stuff.
}
}
}
In Android when you define the android:onClick="someMethod" attribute it only implements the OnClickListener for you.
So it is your responsibility to define the onCLickListener Method and call your ServerButtonClick method from that.
Add this method in your Activity OnCreate Method. It would work.
ServerButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
ServerButtonClick();
}
});
Also, android:onClick method works only if API level > 4 onwards. so if you're targeting Minimum SDK version < 1.6 please do not use it

android app crashing and list view not showing

Every time I try to run the application with the list view in a location in crashes or when i get it working the list view doesnt show up iv tried changing where the list view comes ie after the first frame layout under the fullscreen content and after the frame layout full screen content controls and still cant get it working
here is the active view xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0099cc"
tools:context=".ActiveCheatsView" >
<TextView
android:id="#+id/fullscreen_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:keepScreenOn="true"
android:text="#string/ActiveCheats"
android:textColor="#000000"
android:textSize="50sp"
android:textStyle="bold" />
<!--
This FrameLayout insets its children based on system windows using
android:fitsSystemWindows.
-->
<ListView
android:id="#+id/Games"
android:layout_width="fill_parent"
android:layout_height="410dp" >
</ListView>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true" >
<LinearLayout
android:id="#+id/fullscreen_content_controls"
style="?buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:background="#color/black_overlay"
android:orientation="horizontal"
tools:ignore="UselessParent" >
<Button
android:id="#+id/Button01"
style="?buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/Search" />
</LinearLayout>
</FrameLayout>
and here is the java view
package com.example.activecheats;
import com.example.activecheats.util.SystemUiHider;
import android.annotation.TargetApi;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ListView;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
* An example full-screen activity that shows and hides the system UI (i.e.
* status bar and navigation/system bar) with user interaction.
*
* #see SystemUiHider
*/
public class ActiveCheatsView extends Activity {
/**
* Whether or not the system UI should be auto-hidden after
* {#link #AUTO_HIDE_DELAY_MILLIS} milliseconds.
*/
private static final boolean AUTO_HIDE = true;
/**
* If {#link #AUTO_HIDE} is set, the number of milliseconds to wait after
* user interaction before hiding the system UI.
*/
private static final int AUTO_HIDE_DELAY_MILLIS = 3000;
/**
* If set, will toggle the system UI visibility upon interaction. Otherwise,
* will show the system UI visibility upon interaction.
*/
private static final boolean TOGGLE_ON_CLICK = true;
/**
* The flags to pass to {#link SystemUiHider#getInstance}.
*/
private static final int HIDER_FLAGS = SystemUiHider.FLAG_HIDE_NAVIGATION;
/**
* The instance of the {#link SystemUiHider} for this activity.
*/
private SystemUiHider mSystemUiHider;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_active_cheats_view);
final View controlsView = findViewById(R.id.fullscreen_content_controls);
final View contentView = findViewById(R.id.fullscreen_content);
// Set up an instance of SystemUiHider to control the system UI for
// this activity.
mSystemUiHider = SystemUiHider.getInstance(this, contentView,
HIDER_FLAGS);
mSystemUiHider.setup();
mSystemUiHider
.setOnVisibilityChangeListener(new SystemUiHider.OnVisibilityChangeListener() {
// Cached values.
int mControlsHeight;
int mShortAnimTime;
#Override
#TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
public void onVisibilityChange(boolean visible) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
// If the ViewPropertyAnimator API is available
// (Honeycomb MR2 and later), use it to animate the
// in-layout UI controls at the bottom of the
// screen.
if (mControlsHeight == 0) {
mControlsHeight = controlsView.getHeight();
}
if (mShortAnimTime == 0) {
mShortAnimTime = getResources().getInteger(
android.R.integer.config_shortAnimTime);
}
controlsView
.animate()
.translationY(visible ? 0 : mControlsHeight)
.setDuration(mShortAnimTime);
} else {
// If the ViewPropertyAnimator APIs aren't
// available, simply show or hide the in-layout UI
// controls.
controlsView.setVisibility(visible ? View.VISIBLE
: View.GONE);
}
if (visible && AUTO_HIDE) {
// Schedule a hide().
delayedHide(AUTO_HIDE_DELAY_MILLIS);
}
}
});
// Set up the user interaction to manually show or hide the system UI.
contentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (TOGGLE_ON_CLICK) {
mSystemUiHider.toggle();
} else {
mSystemUiHider.show();
}
}
});
// Upon interacting with UI controls, delay any scheduled hide()
// operations to prevent the jarring behavior of controls going away
// while interacting with the UI.
findViewById(R.id.Button01).setOnTouchListener(
mDelayHideTouchListener);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Trigger the initial hide() shortly after the activity has been
// created, to briefly hint to the user that UI controls
// are available.
delayedHide(100);
}
/**
* Touch listener to use for in-layout UI controls to delay hiding the
* system UI. This is to prevent the jarring behavior of controls going away
* while interacting with activity UI.
*/
View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (AUTO_HIDE) {
delayedHide(AUTO_HIDE_DELAY_MILLIS);
}
return false;
}
};
Handler mHideHandler = new Handler();
Runnable mHideRunnable = new Runnable() {
#Override
public void run() {
mSystemUiHider.hide();
}
};
/**
* Schedules a call to hide() in [delay] milliseconds, canceling any
* previously scheduled calls.
*/
private void delayedHide(int delayMillis) {
mHideHandler.removeCallbacks(mHideRunnable);
mHideHandler.postDelayed(mHideRunnable, delayMillis);
}
private List<Games> gamesList= new ArrayList<Games>();
private List<Games> gamesList;
/** Called when the activity is first created. */
public void onCreate1(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the View layer
setContentView(R.layout.activity_active_cheats_view);
setTitle("ActiveCheats");
// Create Parser for games.xml
GamesParser GamesParser = new GamesParser();
InputStream inputStream = getResources().openRawResource(
R.layout.games);
// Parse the inputstream
GamesParser.parse(inputStream);
setGamesList(com.example.activecheats.GamesParser.getList());
// Create a customized ArrayAdapter
GamesArrayAdapter adapter = new GamesArrayAdapter(
getApplicationContext(), R.layout.games_listitem, countryList);
// Get reference to ListView holder
ListView lv = (ListView) this.findViewById(R.id.Games);
// Set the ListView adapter
lv.setAdapter(adapter);
}
public List<Games> getGamesList() {
return gamesList;
}
public void setGamesList(List<Games> gamesList) {
this.gamesList = gamesList;
}
}
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
try this in your xml file and in your Mianactivity should extend ListActivity

CheckBoxPreference not ticking when selected in PreferencesActivity

When I click the "Settings" page, my CheckBoxPreference shows exactly how I want it to at this stage, however when I select it, the state does not change (i.e. from Unchecked to Checked).
It seems to be retaining the value of false (default) and still running onPreferenceChanged with false as the value passed. I am running code inside my onPreferenceChangedListener that is dependent on the value of the preference that is changed. As it stands I only have one preference in here.
activity_preferences.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceScreen>
<CheckBoxPreference
android:summaryOn="true"
android:summaryOff="false"
android:key="isReg"
android:title="Receive Push Messages"
android:selectable="true"
android:enabled="true"
android:persistent="true" />
</PreferenceScreen>
</PreferenceScreen>
PrefsActivity.java:
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceActivity;
import com.google.android.gcm.GCMRegistrar;
public class PrefsActivity extends PreferenceActivity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.activity_preferences);
Preference isReg = (Preference) findPreference("isReg");
isReg.setOnPreferenceChangeListener(new OnPreferenceChangeListener(){
public boolean onPreferenceChange(Preference pref, Object arg1) {
boolean isReg = getSharedPreferences("PREFERENCE", MODE_PRIVATE).getBoolean("isReg", false);
if (isReg){
ServerUtilities.register(getApplicationContext(), GCMRegistrar.getRegistrationId(getApplicationContext()));
}
else {
ServerUtilities.unregister(getApplicationContext(), GCMRegistrar.getRegistrationId(getApplicationContext()));
}
return isReg;
}
});
}
}
You are using the wrong preference widget as per in the code sample,
Preference isReg = (Preference) findPreference("isReg");
It should have been CheckBoxPreference as in
CheckBoxPreference isReg = (CheckBoxPreference) findPreference("isReg");
Edit
One thing I noticed, you're not handling the preference activity properly...consider this code, always, call the preference's commit method in order to save it!
public class PrefsActivity extends PreferenceActivity implements
OnSharedPreferenceChangeListener{
CheckBoxPreference isReg;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.activity_preferences);
PreferenceManager.setDefaultValues(this,R.xml.activity_preferences, false);
isReg = (CheckBoxPreference)findPreference("isReg");
if (isReg != null){
isReg.setOnPreferenceChangeListener(new OnPreferenceChangeListener(){
#Override
public boolean onPreferenceChange(Preference preference,
Object newValue) {
boolean blnIsReg = Boolean.getBoolean(newValue.toString());
Editor e = _prefs.edit();
e.putBoolean("isReg", blnIsReg);
e.commit();
return true;
}
});
}
}
}
#Override
public void onStart(){
super.onStart();
_prefs = PreferenceManager.getDefaultSharedPreferences(this);
}
The listener that is implemented must be in this fashion, which is how the changes are effective:
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Log.d(TAG, "onSharedPreferenceChanged; key = " + key);
}
By incorporating the listener, the logcat will show that the preference's key is indeed being changed, i.e. "isReg".
Update the values from the shared preferences in onResume()
method
SharedPreferences prefs=PreferenceManager.getDefaultSharedPreferences(PrefsActivity.this);
boolean isReg = prefs.getBoolean("isReg", false);
Hope Try This it will help You

EditText on demand widget

I'd like to have a TextView display text, and when you click/longclick on it, a textbox should "show up" and allow editing of said text. When you're done editing (onkey enter i suppose) it should revert back to a textview with the updated text...
I'm wondering if it's feasable to implement such a widget or should I hack a workaround? Tips and suggestions are very welcome.
If you need further idea of what I mean, just go to your e.g. (windows) skype profile and see for yourself.
EDIT:
Clarification: I'm specifically asking for a widget or such which is a textview until clicked on, then transforms to an edittext containing the same text; once done editing it transforms back to a textview representing the new changed text. Thats what i mean by "edittext on demand widget".
But I'm hoping to get something better than
public class Widget {
TextView text;
EditText edit;
String textToRepresent;
//...
}
You have a few different options here.
First you will have to register an onClick or onLongClick to the TextView that you want to make interactive. Just make sure that the user knows it's clickable
Then have your onClick function start a DialogFragment. I like to create show functions. Note that you can use the support libraries here to make your app backwards compatible.
private void showDialog() {
MyDialogFragment dialog = new MyDialogFragment();
dialog.show(getSupportFragmentManager(), "dialog");
}
The DialogFragment is pretty straight forward. In your onCreateView you'll inflate the View that you'll want to display to the user. You can alternatively wrap it with a simple AlertDialogBuilder if you don't want to go custom.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.your_dialog_layout);
mTitleEditText = (TextView) view.findViewById(R.id.title);
mTitleEditText.setOnClickListener(this);
return view;
}
After your findViewByIds set your onClickListeners.
The last thing you have to take care of is getting data back into your original TextView.
You can do this by creating a public method in your Activity that you can call from inside of your DialogFragment. Something like this
#Override
public void onClick(View v) {
int clickedId = v.getId();
if (clickedId == mDoneButton.getId()) {
MyActivity activity = (MyActivity)getActivity();
mTitle = mTitleEditText.getText().toString();
activity.setText(mTitle);
dismiss();
}
}
I would recommend using a DialogFragment because it will handle your life cycle nicely.
However, another option would be to create a new Activity themed to be a dialog
<activity android:theme="#android:style/Theme.Dialog" />
Then you can startActivityForResult to display your dialog and then capture your results in onActivityResult
Here is my solution. I just give you the basic one. Create a TextView in front of EditText and two Button OK,Cancel (You can change to ImageButton like Skype). Change the visiblity of two view. The code is so simple without comment. You can add some null checking according your logic.
public class CompoundTextView extends RelativeLayout implements OnClickListener {
private EditText edt;
private TextView txt;
RelativeLayout layout;
public SkypeTextView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
edt = (EditText) findViewById(R.id.edt);
txt = (TextView) findViewById(R.id.txt_name);
layout = (RelativeLayout) findViewById(R.id.layout);
Button ok = (Button) findViewById(R.id.ok_btn);
Button cancel = (Button) findViewById(R.id.cancel_btn);
ok.setOnClickListener(this);
cancel.setOnClickListener(this);
txt.setOnClickListener(this);
}
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.ok_btn:
String editString = edt.getText().toString();
txt.setText(editString);
layout.setVisibility(View.INVISIBLE);
txt.setVisibility(View.VISIBLE);
break;
case R.id.cancel_btn:
layout.setVisibility(View.INVISIBLE);
txt.setVisibility(View.VISIBLE);
break;
case R.id.txt_name:
txt.setVisibility(View.INVISIBLE);
layout.setVisibility(View.VISIBLE);
break;
}
}
}
Create a XML skypetextview. You can customize font and background to make it's prettier.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="#+id/txt_name"
android:layout_width="fill_parent"
android:layout_height="100dp"
android:textColor="#FFFFFF"
android:textSize="14sp"
android:background="#ff0000" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
android:id="#+id/layout" >
<EditText
android:id="#+id/edt"
android:layout_width="270dp"
android:layout_height="100dp" />
<Button
android:id="#+id/ok_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/edt"
android:text="OK" />
<Button
android:id="#+id/cancel_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/ok_btn"
android:layout_toRightOf="#id/edt"
android:text="Cancel" />
</RelativeLayout>
</RelativeLayout>
add (or include) this view to the layout you want.
Example :
public class TestActivity extends Activity {
SkypeTextView test;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater inflate = getLayoutInflater();
test = (SkypeTextView ) inflate.inflate(R.layout.compound_text_view,
null);
setContentView(test);
}
PS: i forgot. You should add some underline format for your textview in order to make user notice it clickable
Let a EditText change its background based on its state(Editable or Frozen). Set a background selector that does this.
Use this selector xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_focused="true" android:drawable="#android:drawable/edit_text"/>
<item android:drawable="#android:drawable/screen_background_light_transparent"/>
</selector>
Like I said on thursday... Yul was pretty close but not quite close. He did have a general same idea but (theoretically) rushed into code too early ;)
The TextBoxOnDemand code supplied below is production-ready. The idea is similar to what I wanted to avoid in the OP and what Yul suggested, but with optimal implementation (using a ViewSwitcher instead of a RelativeLayout for instance)
I gathered the resources needed for this in the following articles:
Creating custom view from xml
Declaring a custom android UI element using XML
Defining custom attrs
How to pass custom component parameters in java and xml
http://kevindion.com/2011/01/custom-xml-attributes-for-android-widgets/
and decided to post them here because the official Google "training" docs are useless and are either obsolete (deprecated) or do not cover what I needed. I hope you don't mind me claiming my own bounty, but this is the solution I wanted (and expected, ergo the bounty).
I guess the code will have to do ;)
TextBoxOnDemand.java:
package com.skype.widget;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.text.SpannableString;
import android.text.style.UnderlineSpan;
import android.text.util.Linkify;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.View.OnHoverListener;
import android.view.View.OnLongClickListener;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.ViewSwitcher;
import com.skype.ref.R;
import com.skype.ref.RemoteKeys;
public class TextBoxOnDemand extends ViewSwitcher implements OnClickListener, OnLongClickListener, OnFocusChangeListener, OnHoverListener,
OnEditorActionListener
{
public static final String LOGTAG = "TextBoxOnDemand";
private View btmGuard;
private ImageButton cancel, accept;
private EditText editor;
private RelativeLayout editorLayout;
private TextView face;
private String hint = new String();
private boolean inEditMode = false; //normally this is in textview mode
private boolean inputReady = false;
private String ourData = new String();
private String prefillData = new String();
private String tag = new String(); //usually tag is empty.
private View topGuard;
private int autoLinkMask;// = Linkify.EMAIL_ADDRESSES; //Linkify.ALL;
private ColorStateList textColor, hintColor = null;
public TextBoxOnDemand(Context context)
{
super(context);
build(context);
setEditable(false); //init
}
public TextBoxOnDemand(Context context, AttributeSet attrs)
{
super(context, attrs);
build(context);
init(context, attrs);
setEditable(false); //init
}
public String getPrefillData()
{
return prefillData;
}
public String getTag()
{
return tag;
}
public String getText()
{
Log.d(LOGTAG, "getText() returning '" + ourData + "'");
return ourData;
}
public boolean hasPrefillData()
{
return prefillData.isEmpty();
}
public boolean isEditable()
{
Log.d(LOGTAG, "isEditable() returning " + inEditMode);
return inEditMode;
}
#Override
public void onClick(View v)
{
Log.d(LOGTAG, "onClick(" + v + ")");
if (inEditMode)
{
if (v.equals(accept))
{
if (editor.getEditableText().length() == 0 || editor.getEditableText().length() > 5)
ourData = editor.getEditableText().toString();
setEditable(false);
} else if (v.equals(cancel))
{
setEditable(false);
}
}
}
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event)
{
// Log.d(LOGTAG, "onEditorAction(" + v + ", " + actionId + ", " + event + ") fired!");
Log.d(LOGTAG, "onEditorAction() fired, inputReady = " + inputReady);
if (editor.getEditableText().length() > 0 && editor.getEditableText().length() < (prefillData.length() + 2)) return true; //the user needs to enter something
if (inputReady && (event.getKeyCode() == RemoteKeys.ENTER.keycode() || event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) //always is
{
if (editor.getEditableText().length() > prefillData.length() || editor.getEditableText().length() == 0)
ourData = editor.getEditableText().toString();
setEditable(false);
return false;
}
if ((editor.getEditableText().toString().compareToIgnoreCase(ourData) == 0 || editor.getEditableText().toString()
.compareToIgnoreCase(prefillData) == 0)
&& !inputReady) //means we didn't just keep on holding enter
return true;
else
inputReady = true;
return true;
}
#Override
public void onFocusChange(View v, boolean hasFocus)
{
Log.d(LOGTAG, "onFocusChange(" + v + ", " + hasFocus + ")\tinEditMode = " + inEditMode);
if (inEditMode)
{
if (hasFocus && (v.equals(topGuard) || v.equals(btmGuard)))
{
setEditable(false);
requestFocus();
}
if (hasFocus && (v.equals(editor) || v.equals(accept) || v.equals(cancel)))
{
//do nothing, you should be able to browse freely here
if (ourData.isEmpty() && editor.getEditableText().length() < prefillData.length())
{
Log.d(LOGTAG, "adding prefill, before = " + editor.getEditableText());
editor.setText("");
editor.append(prefillData);
Log.d(LOGTAG, "now is = " + editor.getEditableText());
}
}
} else
{
String text = (ourData.isEmpty()) ? hint : ourData;
ColorStateList color;
if (hintColor != null && ourData.isEmpty())
color = hintColor;
else
color = textColor;
face.setTextColor(color);
if (hasFocus)
{
SpannableString ss = new SpannableString(text);
ss.setSpan(new UnderlineSpan(), 0, text.length(), 0);
face.setText(ss);
} else
face.setText(text);
}
}
#Override
public boolean onHover(View v, MotionEvent event)
{
// Log.d(LOGTAG, "onHover()");
String text = (ourData.isEmpty()) ? hint : ourData;
ColorStateList color;
if (hintColor != null && ourData.isEmpty())
color = hintColor;
else
color = textColor;
face.setTextColor(color);
switch (event.getAction())
{
case MotionEvent.ACTION_HOVER_ENTER:
SpannableString ss = new SpannableString(text);
ss.setSpan(new UnderlineSpan(), 0, text.length(), 0);
face.setText(ss);
break;
case MotionEvent.ACTION_HOVER_EXIT:
face.setText(text);
break;
}
return true;
}
#Override
public boolean onLongClick(View v)
{
Log.d(LOGTAG, "onLongClick()\tinEditMode = " + inEditMode);
if (!inEditMode) //implies that getDisplayedChild() == 0, meaning the textview
{
setEditable(true);
return true;
} else
return false;
}
public void setEditable(boolean value)
{
Log.d(LOGTAG, "setEditable(" + value + ")");
inEditMode = value;
if (inEditMode)
{
//display the editorLayout
face.setOnLongClickListener(null);
face.setOnHoverListener(null);
face.setOnFocusChangeListener(null); //because of GC.
face.setOnClickListener(null);
face.setVisibility(View.GONE);
setDisplayedChild(1);
editorLayout.setVisibility(View.VISIBLE);
editor.setOnFocusChangeListener(this);
editor.setOnEditorActionListener(this);
cancel.setOnClickListener(this);
accept.setOnClickListener(this);
accept.setOnFocusChangeListener(this);
cancel.setOnFocusChangeListener(this);
} else
{
editor.setOnFocusChangeListener(null);
editor.setOnEditorActionListener(null);
cancel.setOnClickListener(null);
accept.setOnClickListener(null);
accept.setOnFocusChangeListener(null);
cancel.setOnFocusChangeListener(null);
editorLayout.setVisibility(View.GONE);
setDisplayedChild(0);
face.setVisibility(View.VISIBLE);
face.setOnLongClickListener(this);
face.setOnHoverListener(this);
face.setOnFocusChangeListener(this);
face.setOnClickListener(this);
face.setFocusable(true);
face.setFocusableInTouchMode(true);
}
updateViews();
}
#Override
public void setNextFocusDownId(int nextFocusDownId)
{
super.setNextFocusDownId(nextFocusDownId);
face.setNextFocusDownId(nextFocusDownId);
// editor.setNextFocusDownId(nextFocusDownId);
accept.setNextFocusDownId(nextFocusDownId);
cancel.setNextFocusDownId(nextFocusDownId);
}
#Override
public void setNextFocusForwardId(int nextFocusForwardId)
{
super.setNextFocusForwardId(nextFocusForwardId);
face.setNextFocusForwardId(nextFocusForwardId);
editor.setNextFocusForwardId(nextFocusForwardId);
}
#Override
public void setNextFocusLeftId(int nextFocusLeftId)
{
super.setNextFocusLeftId(nextFocusLeftId);
face.setNextFocusLeftId(nextFocusLeftId);
editor.setNextFocusLeftId(nextFocusLeftId);
}
#Override
public void setNextFocusRightId(int nextFocusRightId)
{
super.setNextFocusRightId(nextFocusRightId);
face.setNextFocusRightId(nextFocusRightId);
cancel.setNextFocusRightId(nextFocusRightId);
}
#Override
public void setNextFocusUpId(int nextFocusUpId)
{
super.setNextFocusUpId(nextFocusUpId);
face.setNextFocusUpId(nextFocusUpId);
// editor.setNextFocusUpId(nextFocusUpId);
accept.setNextFocusUpId(nextFocusUpId);
cancel.setNextFocusUpId(nextFocusUpId);
}
public void setPrefillData(String prefillData)
{
this.prefillData = new String(prefillData);
}
public String setTag()
{
return tag;
}
public void setText(String text)
{
Log.d(LOGTAG, "setText(" + text + ")");
ourData = text;
updateViews();
}
private void build(Context context)
{
Log.d(LOGTAG, "build()");
addView(View.inflate(context, R.layout.textboxondemand, null));
setFocusable(true);
setFocusableInTouchMode(true);
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
setOnFocusChangeListener(this);
setOnLongClickListener(this);
face = (TextView) findViewById(R.id.TBOD_textview);
editorLayout = (RelativeLayout) findViewById(R.id.TBOD_layout);
editor = (EditText) findViewById(R.id.TBOD_edittext);
accept = (ImageButton) findViewById(R.id.TBOD_accept);
cancel = (ImageButton) findViewById(R.id.TBOD_cancel);
topGuard = (View) findViewById(R.id.TBOD_top);
btmGuard = (View) findViewById(R.id.TBOD_bottom);
face.setFocusable(true);
face.setFocusableInTouchMode(true);
face.setOnLongClickListener(this);
face.setOnHoverListener(this);
face.setOnFocusChangeListener(this);
face.setOnClickListener(this);
editor.setOnFocusChangeListener(this);
editor.setOnEditorActionListener(this);
editor.setHint(hint);
editor.setFocusable(true);
editor.setFocusableInTouchMode(true);
accept.setOnClickListener(this);
accept.setOnFocusChangeListener(this);
accept.setFocusable(true);
cancel.setFocusable(true);
cancel.setOnFocusChangeListener(this);
cancel.setOnClickListener(this);
topGuard.setFocusable(true);
topGuard.setOnFocusChangeListener(this);
btmGuard.setFocusable(true);
btmGuard.setOnFocusChangeListener(this);
editor.setNextFocusRightId(R.id.TBOD_accept);
editor.setNextFocusDownId(R.id.TBOD_bottom);
editor.setNextFocusUpId(R.id.TBOD_top);
accept.setNextFocusLeftId(R.id.TBOD_edittext);
accept.setNextFocusRightId(R.id.TBOD_cancel);
cancel.setNextFocusLeftId(R.id.TBOD_accept);
}
private void init(Context context, AttributeSet attrs)
{
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TextBoxOnDemand);
//Use a
Log.d(LOGTAG, "init()");
if (a == null) Log.d(LOGTAG, "Did you include 'xmlns:app=\"http://schemas.android.com/apk/res-auto\"' in your root layout?");
final int N = a.getIndexCount();
for (int i = 0; i < N; ++i)
{
int attr = a.getIndex(i);
switch (attr)
{
case R.styleable.TextBoxOnDemand_android_hint:
hint = new String(a.getString(attr));
editor.setHint(a.getString(attr));
break;
case R.styleable.TextBoxOnDemand_android_text:
ourData = new String(a.getString(attr));
break;
case R.styleable.TextBoxOnDemand_android_inputType:
int inputType = a.getInt(attr, -1);
if (inputType != -1) editor.setInputType(inputType);
break;
case R.styleable.TextBoxOnDemand_android_textColor:
textColor = a.getColorStateList(attr);
face.setTextColor(textColor);
break;
case R.styleable.TextBoxOnDemand_android_linksClickable:
face.setLinksClickable(a.getBoolean(attr, true));
break;
case R.styleable.TextBoxOnDemand_android_textColorHint:
hintColor = a.getColorStateList(attr);
break;
case R.styleable.TextBoxOnDemand_android_autoLink:
autoLinkMask = a.getInt(attr, 0);
face.setAutoLinkMask(autoLinkMask);
break;
default:
Log.d(LOGTAG, "Skipping attribute " + attr);
}
}
//Don't forget this
a.recycle();
}
private void updateViews()
{
Log.d(LOGTAG, "updateViews()");
// if (getDisplayedChild() == 0) //first child - textview
if (!inEditMode) //first child - textview
{
if (ourData.isEmpty())
{
if (hintColor != null) face.setTextColor(hintColor);
face.setText(hint);
} else
{
face.setTextColor(textColor);
face.setText(ourData);
}
face.setFocusable(true);
face.setFocusableInTouchMode(true);
face.setAutoLinkMask(autoLinkMask);
} else
{ //second child - edittext
editor.setFocusable(true);
editor.setFocusableInTouchMode(true);
if (ourData.startsWith(prefillData) || ourData.length() >= prefillData.length())
editor.setText("");
else
editor.setText(prefillData);
editor.append(ourData);
inputReady = false;
editor.requestFocus();
}
}
public void setAutoLinkMask(LinkifyEnum linkifyEnumConstant)
{
switch (linkifyEnumConstant)
{
case ALL:
autoLinkMask = Linkify.ALL;
break;
case EMAIL_ADDRESSES:
autoLinkMask = Linkify.EMAIL_ADDRESSES;
break;
case MAP_ADDRESSES:
autoLinkMask = Linkify.MAP_ADDRESSES;
break;
case PHONE_NUMBERS:
autoLinkMask = Linkify.PHONE_NUMBERS;
break;
case WEB_URLS:
autoLinkMask = Linkify.WEB_URLS;
break;
case NONE:
default:
autoLinkMask = 0;
break;
}
//set it now
face.setAutoLinkMask(autoLinkMask);
}
public enum LinkifyEnum
{
ALL, EMAIL_ADDRESSES, MAP_ADDRESSES, PHONE_NUMBERS, WEB_URLS, NONE
};
}
I'm still working out some focus-related issues but this works as intended. When I use onFocuslistener 1, you can't focus from one TextBox to the other; when the textbox itself is focusable, I can focus from one to the other just fine, but I cannot inter-focus thru children and thus can't focus on the edittext to type.
the XML file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/TBOD_textview"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:autoLink="email"
android:focusable="true"
android:focusableInTouchMode="true"
android:linksClickable="true"
android:textAppearance="?android:attr/textAppearanceMedium" />
<RelativeLayout
android:id="#+id/TBOD_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<EditText
android:id="#+id/TBOD_edittext"
android:layout_width="300dp"
android:layout_height="30dp"
android:layout_below="#+id/TBOD_textview"
android:focusable="true"
android:focusableInTouchMode="true"
android:imeOptions="actionDone"
android:inputType="none"
android:maxLines="1"
android:padding="2dp"
android:singleLine="true"
android:textColor="#android:color/black"
android:textSize="14dp" />
<ImageButton
android:id="#+id/TBOD_accept"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="#+id/TBOD_edittext"
android:layout_marginLeft="15dp"
android:layout_toRightOf="#+id/TBOD_edittext"
android:background="#drawable/button_accept_selector" />
<ImageButton
android:id="#+id/TBOD_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="#+id/TBOD_edittext"
android:layout_marginLeft="5dp"
android:layout_toRightOf="#+id/TBOD_accept"
android:background="#drawable/button_cancel_selector" />
<View
android:id="#+id/TBOD_top"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_alignParentTop="true"
android:background="#android:color/transparent" />
<View
android:id="#+id/TBOD_bottom"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_alignParentBottom="true"
android:background="#android:color/transparent" />
</RelativeLayout>
</RelativeLayout>
and finally, the attrs.xml file:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TextBoxOnDemand">
<attr name="android:text" />
<attr name="android:inputType" />
<attr name="android:hint" />
<attr name="android:textColor" />
<attr name="android:textColorHint" />
<attr name="android:linksClickable" />
<attr name="android:autoLink" />
</declare-styleable>
</resources>
This is how I used it in my main xml (after including the required namespace add):
<com.shark.widget.TextBoxOnDemand
android:id="#+id/profile_email2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/profile_skypename"
android:layout_below="#+id/profile_email_placeholder"
android:hint="#string/add_email"
android:inputType="textEmailAddress"
android:textColor="#android:color/white"
android:textColorHint="#color/skype_blue" />
EDIT: I've debugged the focus issues. It turns out that giving focus to children is difficult unless you call
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
Which kinda remedies the issue but still doesn't solve it. After some while of playing around with the onFocusChange() listener still trying to get the perfect behaviour, I threw in the towel and put in added two focus guards. I realized I cannot track the loss of focus only on my container (due to it never receiving focus) but I might as well track the idea of wanting to move away from the edit field... So i went the dirty route and added two invisible bar-like views to sandwitch the edittext in between. Once they got the focus, I could hide the component and ensure they transition properly.
And there it is, now it works as it should. Thanks to all who participated.
EDIT3: final polished version, i dumped the custom tags because they simply don't work reliably enough. Lesson to be learned: if there is an android tag for something, don't bother cloning it.

Categories