I'm new to Android dev and I'm trying to run a legacy app. Now I'm facing a problem with TextInputLayout. I have the following code:
public class LoginActivity extends AppCompatActivity {
#Bind(R.id.login_input_user)
TextInputLayout login_input_user;
#Bind(R.id.login_input_password)
TextInputLayout login_input_password;
#Bind(R.id.login_bt_enter)
Button login_bt_enter;
#Bind(R.id.login_version)
TextView login_version;
private String username;
private String password;
private Context mContext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
mContext = getApplicationContext();
LoginServices.invalidateAccessToken();
ButterKnife.bind(this);
initViews();
}
private void initViews() {
if (BuildConfig.DEBUG) {
username = "test";
password = "test";
if (login_input_user.getEditText() != null)
login_input_user.getEditText().setText(username);
if (login_input_password.getEditText() != null)
login_input_password.getEditText().setText(password);
} else if (login_input_user.getEditText() != null) {
login_input_user.getEditText().setText(LoginServices.getCurrentLogin());
username = LoginServices.getCurrentLogin();
}
new BindValue(login_input_user).setBind(value -> username = value.toString());
new BindValue(login_input_password).setBind(value -> password = value.toString());
login_bt_enter.setOnClickListener(v -> {
Device.hideSoftKeyboard(LoginActivity.this);
if (isValidLogin()) {
if (Device.hasNetwork()) {
doLogin();
} else {
CustomAlert.showAlertMessage(LoginActivity.this, R.string.alerta_error, R.string.message_no_network);
}
} else {
CustomAlert.showAlertMessage(LoginActivity.this, R.string.alerta_error, R.string.login_error);
}
});
login_version.setText(String.format(getString(R.string.login_version_text), BuildConfig.BUILD_TYPE, BuildConfig.VERSION_NAME));
}
}
This is my activity_login.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/windowLoginBackground"
android:padding="8dp"
android:theme="#style/AppTheme">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="#+id/login_logo"
android:layout_width="200dp"
android:layout_height="100dp"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="48dp"
android:layout_marginTop="48dp"
android:contentDescription="#string/login_logo_contentdescription"
android:scaleType="fitEnd"
android:src="#mipmap/app_logo" />
<android.support.design.widget.TextInputLayout
android:id="#+id/login_input_user"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/login_lb_user"
android:inputType="textEmailAddress" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="#+id/login_input_password"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/login_lb_password"
android:inputType="textPassword" />
</android.support.design.widget.TextInputLayout>
<Button
android:id="#+id/login_bt_enter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="#color/colorAccent"
android:text="#string/login_bt_enter"
android:textColor="#color/white" />
</LinearLayout>
<TextView
android:id="#+id/login_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:text="Versão: 1.0.0" />
When I hit initViews and get this line if (login_input_user.getEditText() != null) I get a NullPointerException. Looks like login_input_user is null.
Where can I initiate this?
This code has been already built and distributed some time ago. They used a previous version of Android Studio and I had to upgrade it to 3.0 and it's plugins to necessary versions to run. So this code once worked fine.
Not sure is it helps, but I can't comment questions yet.
Try to check which version of Butterknife you are using.
If you also updated the libs version it may break it.
After 8 version, annotations was changed.
#Bind becomes #BindView and #BindViews (one view and multiple views,
respectively).
https://github.com/JakeWharton/butterknife/blob/master/CHANGELOG.md
Try this
if (login_input_user.getEditText().toString() != null)
OR
if(login_input_user.getEditText().toString().trim().length() == 0)
Related
I am learning mvvm structure and making an app using mvvm structure and data binding also.
Now, what I want to do is, I wanted to fetch a user from sharedpreference, If I am getting a user successfully then, I would set the name of usr to edittext1. In that case, I want to request focus on edittext2.
How to achieve that using databinding? (in such a way that i don't
have to use activity. The job should be done using view model and xml
only.)
I have tried that using following way.
StartGameViewModel
public class StartGameViewModel extends ViewModel {
public static String TAG="StartGameViewModel";
private Preference<User> preference;
public ObservableField<String> player1Name=new ObservableField<>("");
public ObservableField<String> player2Name=new ObservableField<>("");
public ObservableBoolean shouldRequestFocus=new ObservableBoolean(false);
StartGameViewModel(Preference preference){
this.preference=preference;
}
public void getPreference() {
preference.get(Constants.CURRENT_USER,User.class)
.subscribe(new Observer<User>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(User user) {
player1Name.set(user.name);
shouldRequestFocus.set(true);
}
#Override
public void onError(Throwable e) {
Log.i(TAG,"user is logged out");
}
#Override
public void onComplete() {
Log.i(TAG,"Completed Preference");
}
});
}
}
activity_start_game.xml
<?xml version="1.0" encoding="utf-8"?>
<layout 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"
tools:context=".view.StartGameActivity">
<data>
<variable
name="startGameViewModel"
type="com.sevenbits.android.mvvmsample.viewmodel.StartGameViewModel" />
</data>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/splash_bg">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Enter Players Name"
android:textSize="24sp"
android:textColor="#color/white"
app:layout_constraintVertical_bias="0.75"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toTopOf="#+id/input_layout"
app:layout_constraintTop_toTopOf="parent"
/>
<LinearLayout
android:id="#+id/input_layout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:background="#color/white"
android:elevation="20dp"
android:orientation="vertical"
android:paddingBottom="40dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingTop="40dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.45"
tools:layout_editor_absoluteX="8dp">
<android.support.design.widget.TextInputLayout
android:id="#+id/til_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<android.support.design.widget.TextInputEditText
android:id="#+id/et_player1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Player1"
android:text="#{startGameViewModel.player1Name}"
app:addTextChangedListener="#{startGameViewModel.Player1Watcher}" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="#+id/til_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<android.support.design.widget.TextInputEditText
android:id="#+id/et_player2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Player2"
android:text="#{startGameViewModel.player2Name}"
app:addTextChangedListener="#{startGameViewModel.Player2Watcher}" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>
<Button
android:id="#+id/start_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/bg_button"
android:elevation="20dp"
android:gravity="center"
android:paddingBottom="20dp"
android:paddingEnd="40dp"
android:paddingStart="40dp"
android:paddingTop="20dp"
android:text="Start"
android:textAllCaps="false"
android:textColor="#color/white"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/input_layout" />
</android.support.constraint.ConstraintLayout>
</layout>
StartGameActivity:
public class StartGameActivity extends AppCompatActivity {
ActivityStartGameBinding activityStartGameBinding;
StartGameViewModel startGameViewModel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initDataBinding();
setStartGameListener();
}
private void initDataBinding() {
activityStartGameBinding = DataBindingUtil.setContentView(this, R.layout.activity_start_game);
StartGameViewModelFactory startGameViewModelFactory= Injection.provideStartGameViewModelFactory(this);
startGameViewModel = ViewModelProviders.of(this,startGameViewModelFactory).get(StartGameViewModel.class);
activityStartGameBinding.setStartGameViewModel(startGameViewModel);
startGameViewModel.getPreference();
if(startGameViewModel.shouldRequestFocus.get())
findViewById(R.id.et_player2).requestFocus();
}
private void setStartGameListener() {
findViewById(R.id.start_button).setOnClickListener(v -> {
Intent intent=new Intent(StartGameActivity.this,GameActivity.class);
intent.putExtra(Constants.PLAYER1_NAME,startGameViewModel.player1Name.get());
intent.putExtra(Constants.PLAYER2_NAME,startGameViewModel.player2Name.get());
startActivity(intent);
});
}
}
Very simple via binding adapter
#JvmStatic
#BindingAdapter("requestFocus")
fun requestFocus(view: TextView, requestFocus: Boolean) {
if (requestFocus) {
view.isFocusableInTouchMode = true
view.requestFocus()
}
}
<EditText
android:id="#+id/et_company"
android:layout_width="0dp"
android:layout_height="match_parent"
android:imeOptions="actionDone"
android:inputType="textCapSentences"
android:maxLength="32"
android:scrollbars="vertical"
app:requestFocus="#{company.requestFocus}" />
I know this is an old question, but I was not able to solve the issue with the current answer. Posting my answer here:
in XML:
<EditText
android:id="#+id/email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="#dimen/elevation15"
app:requestFocus="#{viewmodel.focus}"/>
And in the viewModel, I had a Boolean variable declared as
val focus = true
And the binding adapter is as follows:
companion object{
#BindingAdapter("requestFocus")
#JvmStatic fun requestFocus(editText: EditText, requestFocus: Boolean){
if(requestFocus){
editText.isFocusableInTouchMode = true
editText.requestFocus()
}
}
}
Basically what is happening here is, Since app:requestFocus is written inside the xml, it will invoke the binding adapter with the focus Boolean, which is given as the value for the attribute for app:requestFocus.
In my case, I didn't want to remove focus, that's why I used Boolean. If it needs to be changed, using a livedata and set the value, and update the binding adapter accordingly
Disclaimer: I am new to MVVM and Databinding, someone please correct me if I am wrong.
I have a button in a DialogFragment to go back to another activity. But it only works when double-clicked. I'm running out of ideas. In my XML file, I've already tried the following (combined in different ways, but none of them worked)
My whole fragment XML file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="600dp"
android:layout_height="500dp"
android:layout_gravity="center"
android:background="#drawable/bg_rounded_white"
android:gravity="center"
android:orientation="vertical"
android:padding="#dimen/vertical_margin">
<TextView
android:id="#+id/tv_payment_done_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/vertical_margin"
android:gravity="center_horizontal"
android:text="#string/payment_approved_title"
android:textColor="#color/bg_color"
android:textSize="#dimen/text_large"
android:textStyle="bold" />
<TextView
android:id="#+id/tv_payment_message"
android:layout_width="550dp"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/vertical_margin"
android:gravity="center_horizontal"
android:minHeight="100dp"
android:text="Payment done!"
android:textColor="#color/black_overlay"
android:textSize="#dimen/text_medium"
android:textStyle="normal" />
<LinearLayout
android:layout_width="600dp"
android:layout_height="80dp"
android:layout_marginTop="46dp"
android:clickable="false"
android:focusable="false"
android:gravity="center"
android:orientation="horizontal">
<Button
android:id="#+id/rpv_btn_no_payment_done"
android:layout_width="250dp"
android:layout_height="?android:attr/actionBarSize"
android:background="#drawable/bg_rounded_light_blue"
android:duplicateParentState="true"
android:text="#string/txt_btn_no"
android:textAllCaps="false"
android:textColor="#color/white_text_color"
android:textSize="#dimen/text_medium"
android:textStyle="bold"
android:visibility="gone" />
<Button
android:id="#+id/rpv_btn_yes_payment_done"
android:layout_width="250dp"
android:layout_height="?android:attr/actionBarSize"
android:layout_marginLeft="#dimen/vertical_margin"
android:background="#drawable/bg_rounded_light_blue"
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:focusedByDefault="true"
android:text="#string/txt_btn_exit"
android:textAllCaps="false"
android:textColor="#color/white_text_color"
android:textSize="#dimen/text_medium"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
As for my DialogFragment, I've tried to put my setOnClickListener inside the onViewCreated() method, and then inside the onStart() and after inside the onResume() methods. It keeps working only when double-clicked. I also have a timer that makes the dialog disappear after 10 secs and then it leads me to the activity I want anyway, so it isn't so much of a problem, but I really need and want to fix it. If I set the timer to 5 secs or lower, of course, it gives the impression that the button works when clicked once, but it actually doesn't.
class PaymentDoneDialogFragment : DialogFragment() {
private lateinit var mYesBtn: Button
private lateinit var mActionYes: () -> Unit
override fun onViewCreated(view: View, #Nullable savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
dialog.setCanceledOnTouchOutside(false)
dialog.window.requestFeature(Window.FEATURE_NO_TITLE)
dialog.window.setDimAmount(.85f)
dialog.window.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
dialog.setCancelable(false)
dialog.setCanceledOnTouchOutside(false)
dialog.window.decorView.systemUiVisibility = activity?.window!!.decorView.systemUiVisibility
dialog.window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
mDialogTitle = view.find(R.id.tv_payment_done_title)
if (mTitle != null) {
mDialogTitle.text = mTitle
}
mYesBtn = view.find(R.id.rpv_btn_yes_payment_done)
if (mYesTitle != null) {
mYesBtn.text = mYesTitle
}
mYesBtn.setOnClickListener {
if (mMessage == null) {
(activity as PaymentActivity).nextScreensaverActivity()
} else {
mActionYes()
}
activity?.supportFragmentManager?.beginTransaction()?.remove(this)?.commit()
}
if (mMessage != null) {
mMessageTextView = view.find(R.id.tv_payment_message)
mMessageTextView?.text = mMessage
mNoBtn = view.find(R.id.rpv_btn_no_payment_done)
if (mNoTitle != null)
mNoBtn.text = mNoTitle
mNoBtn.visibility = View.VISIBLE
mNoBtn.setOnClickListener {
mActionNo()
activity?.supportFragmentManager?.beginTransaction()?.remove(this)?.commit()
}
}
}
Does anyone have some clue?
You should remove android:clickable="false" and android:focusable="false" from LinearLayout child
I have a form where the user enter the client info. When I try to validate the fields I have a problem, I used editText.setError(errorMessage) and it's showing the error message, but it shown on the top of my EditText making it confusing to the user. Like the image below.
Any ideas of how I can fix this?
EditText on XML
<LinearLayout
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:orientation="vertical"
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="br.com.intelecto.intesigmobile.activity.ClienteEditActivityFragment">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/et_nome"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/cliente_nome"
android:imeActionId="#+id/cli_name"
android:imeActionLabel="#string/str_next"
android:imeOptions="actionUnspecified"
android:inputType="textPersonName"
android:maxLines="1"
android:singleLine="true"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/et_telefone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/cliente_telefone"
android:imeActionId="#+id/cli_cpf"
android:imeActionLabel="#string/str_next"
android:imeOptions="actionUnspecified"
android:inputType="phone"
android:maxLines="1"
android:singleLine="true"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/et_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/cliente_email"
android:imeActionId="#+id/cli_cpf"
android:imeActionLabel="#string/str_next"
android:imeOptions="actionUnspecified"
android:inputType="textEmailAddress"
android:maxLines="1"
android:singleLine="true"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/et_cpf"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/cliente_cpf"
android:imeActionId="#+id/cli_cpf"
android:imeActionLabel="#string/str_next"
android:imeOptions="actionUnspecified"
android:inputType="number"
android:maxLines="1"
android:singleLine="true"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/et_endereco"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/cliente_endereco"
android:imeActionId="#+id/cli_address"
android:imeActionLabel="#string/str_next"
android:imeOptions="actionUnspecified"
android:inputType="textPostalAddress"
android:maxLines="1"
android:singleLine="true"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/et_bairro"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/cliente_bairro"
android:imeActionId="#+id/cli_district"
android:imeActionLabel="#string/str_next"
android:imeOptions="actionUnspecified"
android:inputType="text"
android:maxLines="1"
android:singleLine="true"/>
</android.support.design.widget.TextInputLayout>
<Spinner
android:id="#+id/sp_estados"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"/>
<Spinner
android:id="#+id/sp_cidade"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:prompt="#string/cliente_cidade"/>
This ClienteEditActivity holds two fragments with different forms so I listen for a action menu click at the fragment, when menu is clicked I use this to call may validation:
if (!isValidEmail(etEmail)) {
cancel = true;
focusView = etEmail;
}
//after other validations
if (cancel){
focusView.reqeustFocus();
} else {
//save datas
}
The isValidEmail method is like this:
protected boolean isValidEmail(EditText editText) {
validate = new Validate(editText);
validate.addValidador(new ValidadorVazio(getContext()));
validate.addValidador(new ValidadorEmail(getContext()));
return validate.isValid();
}
My Validateclass looks like this:
public class Validate{
private EditText etFonte;
public Validate(EditText etFonte){
this.etFonte = etFonte;
}
public void addValidador(AbstractValidador validador){
lalidadores.add(validador);
}
public boolean isValid(){
for (AbstractValidador validator : lValidadores) {
try {
if (!validator.isValid(etFonte.getText().toString())) {
if(errorNotification != null) {
errorNotification.onInvalid(this);
} else {
setSourceViewError(validator.getMessage(), validator.getErrorDrawable());
}
return false;
} else {
if(errorNotification != null) errorNotification.onValid(this);
}
} catch (ValidadorException e) {
e.printStackTrace();
if(errorNotification != null) {
errorNotification.onInvalid(this);
} else {
setSourceViewError(e.getMessage(),validator.getErrorDrawable());
}
return false;
}
}
etFonte.setError(null);
return true;
}
private void setSourceViewError(String errorMessage, Drawable errorDrawable) {
if(errorDrawable != null) {
etFonte.setError(errorMessage, errorDrawable);
} else {
etFonte.setError(errorMessage);
}
}
}
Set error on TextInputLayout instead of EditText, Here's your code...
<android.support.design.widget.TextInputLayout
android:id="#+id/textInputLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/et_nome"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/cliente_nome"
android:imeActionId="#+id/cli_name"
android:imeActionLabel="#string/str_next"
android:imeOptions="actionUnspecified"
android:inputType="textPersonName"
android:maxLines="1"
android:singleLine="true"/>
Get your TextInputLayout at runtime and apply following code...
TextInputLayout textInputLayout = (TextInputLayout) findVeiwById(R.id.textInputLayout);
textInputLayout.setErrorEnabled(true);
textInputLayout.setError("Please enter a valid license number");
It will produce output something like this...
In your layout's root element, find the following line and remove it.
app:layout_behavior="#string/appbar_scrolling_view_behavior"
Everything will be fine!
I assume that you have set an error on wrong reference of edit text. You have to set error on the same edit email edit text and also have to request focus on same edit text.
Here is the code snippet for activity:-
private EditText mEmailET;
#Override
protected void onCreate(Bundle savedInstanceState) {
mEamilET = (EditText)findViewById(R.id.et_email);
}
private void setSourceViewError(String errorMessage, Drawable errorDrawable) {
if(errorDrawable != null) {
mEamilET.setError(errorMessage, errorDrawable);
mEamilET.requestFocus();
} else {
mEamilET.setError(errorMessage);
mEamilET.requestFocus();
}
}
If you still face the issue please send the activity code too for better understanding for us and appropriate answer.
Do not use "include" tag to show your layout. Just replace that tag with your layout and you good to go. And you would want to set marginTop="60dp" so the toolbar is accessible.
I am new in android development. I start for android accessibility work to make android application accessible for blind people. I made simple login form and set accessibility attribute such as content description and focus etc I turn on talk back and check it.
here is code activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="#string/usernm_text"
android:id="#+id/username"
android:contentDescription="#string/usernm_text"
android:focusable="true"
android:nextFocusDown="#+id/usr_nm"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:ems="10"
android:id="#+id/usr_nm"
android:contentDescription="#string/usernm_text"
android:focusable="true"
android:text="admin"
android:nextFocusDown="#+id/password"
android:nextFocusUp="#id/usr_nm"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="#string/pass_text"
android:id="#+id/password"
android:focusable="true"
android:nextFocusDown="#+id/pass_edit"
android:contentDescription="#string/pass_text"
android:nextFocusUp="#id/usr_nm"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:ems="10"
android:id="#+id/pass_edit"
android:contentDescription="#string/pass_text"
android:text="admin"
android:focusable="true"
android:nextFocusDown="#+id/login"
android:nextFocusUp="#id/password"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/login_btn"
android:onClick="log"
android:id="#+id/login"
android:contentDescription="#string/login_btn"
android:focusable="true"
android:nextFocusUp="#id/pass_edit"
android:accessibilityLiveRegion="polite" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:id="#+id/log_succ"
android:focusable="true"
android:accessibilityLiveRegion="polite" />
</LinearLayout>
in my MainActivity.java
public class MainActivity extends AppCompatActivity {
EditText usr_nm;
TextView log_succ;
Button logs;
EditText pass_edit;
int counter=5;
String log_msg="login successful";
Button log_btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
log_succ=(TextView) findViewById(R.id.log_succ);
usr_nm=(EditText) findViewById(R.id.usr_nm);
pass_edit=(EditText)findViewById(R.id.pass_edit);
}
public void log(View view) {
if (usr_nm.getText().toString().equals("admin") &&
pass_edit.getText().toString().equals("admin")) {
log_succ.setText(log_msg);
log_succ.setContentDescription("Login successful");
// log_succ.isFocusable();
// Toast.makeText(MainActivity.this, "password is correct", Toast.LENGTH_LONG).show();
// Intent in = new Intent("com.example.samir.login_form.user_page");
// startActivity(in);
} else {
Toast.makeText(MainActivity.this, "password is incorrect", Toast.LENGTH_SHORT).show();
counter--;
if (counter == 0)
logs.setEnabled(false);
}
}
login successful textview prompt by talkback when touch it.
i want that when i click on login button then textview "Login successful" should be prompt by talkback immediately.
I set AccessibilityliveRegion to "polite".
what else should i do??
From what i understood, you want the system to speak up "Login Successful" after the user logs in.
You can achieve this using TextToSpeech class.
First declare an object of TextToSpeech (a Global/Class variable):
TextToSpeech tts;
Then set it to instantiate & speak up when your login process is successful:
tts = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if(status == TextToSpeech.SUCCESS){
tts.setLanguage(Locale.US);
tts.speak("Login Successful", TextToSpeech.QUEUE_FLUSH, null);
}
}
});
Also, don't forget to release the resources after you are done:
#Override
protected void onPause() {
if(tts!=null){
tts.stop();
tts.shutdown();
}
super.onPause();
}
Hope this helps.
This is possible if we set android:accessibilityLiveRegion="polite" for textview .. thank you for your reply.
In my project, im going to make a multiple choice type question. I can select the questions and answer from mysql, however, i cant do the "matching" of the answer between input answer and the data from mysql. I tried some solutions but they doesnt work as well. I need a big help on it. Below are my codes.
the java class that make multiple choice
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.normalmode);
new DataAsyncTask().execute();
}
public void onClick(View v){
inputtext = ((Button) v).getText().toString();
tv3 = (TextView)findViewById(R.id.textView3);
tv3.setText(inputtext);
if(inputtext == tv2.getText().toString()){
playerscore +=5;
} else {
playerscore +=1;
}
score.setText("Scores : " + playerscore);
new DataAsyncTask().execute();
}
class DataAsyncTask extends AsyncTask<String, String, String>{
#Override
protected String doInBackground(String... param) {
String result = DBConnector.executeQuery("SELECT * FROM questions ORDER BY RAND( ) LIMIT 1");
return result;
}
#Override
protected void onPostExecute(String result) {
question = (TextView)findViewById(R.id.textView_question);
fchoice = (Button)findViewById(R.id.Btn_choice1);
schoice = (Button)findViewById(R.id.Btn_choice2);
tchoice = (Button)findViewById(R.id.Btn_choice3);
tv2 = (TextView)findViewById(R.id.textView2);
score = (TextView)findViewById(R.id.textView_score);
try {
JSONArray jsonArray = new JSONArray(result);
JSONObject jsonData = jsonArray.getJSONObject(0);
question.setText(jsonData.getString("q_desc"));
fchoice.setText(jsonData.getString("fchoice"));
schoice.setText(jsonData.getString("schoice"));
tchoice.setText(jsonData.getString("tchoice"));
ans = jsonData.getString("q_ans");
tv2.setText(ans);
} catch(Exception e) {
Log.e("log_tag", e.toString());
}
}
}
}
three buttons are sharing same onClick in xml file by using
android:onClick="onClick"
the current problem i faced is that it always return "false" no matter i pressed which button. also, is there any way to store/pass "previous" async task data?
I have tried using internal storage but it doesnt work as well
EDIT:
my xml file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.95" >
<TextView
android:id="#+id/textView_score"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/player_score" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.95" >
<TextView
android:id="#+id/textView_question"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="#string/string_question"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Button
android:id="#+id/Btn_choice3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:text="#string/third_choice"
android:onClick="onClick" />
<Button
android:id="#+id/Btn_choice2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/Btn_submit"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:text="#string/second_choice"
android:onClick="onClick" />
<Button
android:id="#+id/Btn_choice1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/Btn_choice2"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:text="#string/first_choice"
android:onClick="onClick" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="TextView" />
<TextView
android:id="#+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/textView1"
android:text="TextView" />
</RelativeLayout>
</LinearLayout
textview2 and textview3 are used to test my output and display them as text
try this if(inputtext.equals(tv2.getText().toString())) instead of if(inputtext == tv2.getText().toString())
becasue the == operator checks to see if the two strings are exactly the same object.
The .equals() method will check if the two strings have the same value.