1

在图形布局中显示良好,然后当我在模拟器中启动时它会这样做 http://imgur.com/zR0xncU

我认为这可能是视图膨胀的问题,或者我不确定我是 android 新手。请帮助我已经尝试解决这个愚蠢的布局问题好几个小时了。谢谢

package com.keyconsultant.parse.logintutorial;

import java.util.Locale;

import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.TextView;

import com.keyconsultant.parse.logintutorial.error.UnknownErrorDialogFactory;
import com.keyconsultant.parse.logintutorial.fragment.BaseFragment;
import com.keyconsultant.parse.logintutorial.model.user.UserManager;
import com.keyconsultant.parse.logintutorial.model.user.authenticate.AuthenticateUserErrorEvent;
import com.parse.ParseException;
import com.squareup.otto.Subscribe;

/**
 * Fragment for logging in. Includes button for loading the Create account view. 
 * 
 * @author Trey Robinson
 *
 */
public class LoginFragment extends BaseFragment {

    public static final String EXTRA_USERNAME = "com.keyconsultant.parse.logintutorial.activity.extra.USERNAME";
    public static final String EXTRA_PASSWORD = "com.keyconsultant.parse.logintutorial.activity.extra.PASSWORD";

    // UI references.
    private EditText mUserNameEditText;
    private EditText mPasswordEditText;

    /**
     * Factory method for creating new fragments
     * @return
     */
    public static LoginFragment newInstance(){
        return new LoginFragment();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {


        View view = inflater.inflate(R.layout.fragment_login, container, false);
        mUserNameEditText = (EditText) view.findViewById(R.id.username);

        mPasswordEditText = (EditText) view.findViewById(R.id.password);
        mPasswordEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
                if (id == EditorInfo.IME_NULL) {
                    attemptLogin();
                    return true;
                }
                return false;
            }
        });

        view.findViewById(R.id.sign_in_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                attemptLogin();
            }
        });

        view.findViewById(R.id.register_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                createAccount();
            }
        });
        return view;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if(savedInstanceState != null){
            mUserNameEditText.setText(savedInstanceState.getString(EXTRA_USERNAME));
            mPasswordEditText.setText(savedInstanceState.getString(EXTRA_PASSWORD));
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString(EXTRA_USERNAME, mUserNameEditText.getText().toString());
        outState.putString(EXTRA_PASSWORD, mPasswordEditText.getText().toString());
    }

    /**
     * Attempts to sign in or register the account specified by the login form.
     * If there are form errors (invalid email, missing fields, etc.), the
     * errors are presented and no actual login attempt is made.
     */
    public void attemptLogin() {

        clearErrors();

        // Store values at the time of the login attempt.
        String username = mUserNameEditText.getText().toString();
        String password = mPasswordEditText.getText().toString();

        boolean cancel = false;
        View focusView = null;

        // Check for a valid password.
        if (TextUtils.isEmpty(password)) {
            mPasswordEditText.setError(getString(R.string.error_field_required));
            focusView = mPasswordEditText;
            cancel = true;
        } else if (password.length() < 4) {
            mPasswordEditText.setError(getString(R.string.error_invalid_password));
            focusView =mPasswordEditText;
            cancel = true;
        }

        // Check for a valid email address.
        if (TextUtils.isEmpty(username)) {
            mUserNameEditText.setError(getString(R.string.error_field_required));
            focusView = mUserNameEditText;
            cancel = true;
        }

        if (cancel) {
            // There was an error; don't attempt login and focus the first
            // form field with an error.
            focusView.requestFocus();
        } else {
            // perform the user login attempt.
            UserManager.getInstance().authenticate(username.toLowerCase(Locale.getDefault()), password);
        }
    }

    /**
     * Load the create account view. 
     */
    private void createAccount(){
        FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        fragmentTransaction.replace(((ViewGroup)getView().getParent()).getId(), CreateAccountFragment.newInstance());
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();
    }

    /**
     * Remove all edit text errors
     */
    private void clearErrors(){
        mUserNameEditText.setError(null);
        mPasswordEditText.setError(null);
    }

    @Subscribe
    public void onSignInError(AuthenticateUserErrorEvent event){
        clearErrors();
        switch (event.getErrorCode()) {
        case ParseException.OBJECT_NOT_FOUND:
            mPasswordEditText.setError(getString(R.string.error_incorrect_password));
            mPasswordEditText.requestFocus();
            break;
        default:
            UnknownErrorDialogFactory.createUnknownErrorDialog(this.getActivity()).show();
            break;
        }
    }
}

这是 XML

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    style="@style/LoginFormContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#f1c40f"
    android:orientation="vertical" >

    <EditText
        android:id="@+id/username"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/usernameHint"
        android:maxLines="1"
        android:singleLine="true" />

    <EditText
        android:id="@+id/password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/prompt_password"
        android:imeActionId="@+id/login"
        android:imeActionLabel="@string/action_sign_in_short"
        android:imeOptions="actionUnspecified"
        android:inputType="textPassword"
        android:maxLines="1"
        android:singleLine="true" />

    <Button
        android:id="@+id/sign_in_button"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="16dp"
        android:text="@string/action_sign_in_short" />

    <TextView
        android:id="@+id/orTV"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="16dp"
        android:text="@string/orText" />

    <Button
        android:id="@+id/register_button"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="16dp"
        android:text="@string/action_register" />

</LinearLayout>

这是基本片段类

package com.keyconsultant.parse.logintutorial.fragment;

import com.squareup.otto.BusProvider;

import android.support.v4.app.Fragment;

/**
 * Fragment class that resolves basic service bus requirement (Register, deregister, Event Posting)
 * 
 * @author Trey Robinson
 *
 */
public class BaseFragment extends Fragment {
    @Override
    public void onResume() {
        super.onResume();
        BusProvider.getInstance().register(this);

    }

    @Override
    public void onPause() {
        /**fragment must be removed from the service bus in onPause or an error will occur
          when the bus attempts to dispatch an event to the paused activity. **/ 
        BusProvider.getInstance().unregister(this);
        super.onPause();
    }

    /**
     * Post the event to the service bus
     * @param event
     *      The event to dispatch on the service bus
     */
    protected void postEvent(Object event) {
        BusProvider.getInstance().post(event);
    }
}

这是我添加 LOGINFRAGMENT 类的代码

package com.keyconsultant.parse.logintutorial;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

import com.keyconsultant.parse.logintutorial.activity.BaseActivity;
import com.keyconsultant.parse.logintutorial.forgotpassword.ForgotPasswordDialogFragment;
import com.keyconsultant.parse.logintutorial.model.user.authenticate.AuthenticateUserErrorEvent;
import com.keyconsultant.parse.logintutorial.model.user.authenticate.AuthenticateUserStartEvent;
import com.keyconsultant.parse.logintutorial.model.user.authenticate.AuthenticateUserSuccessEvent;
import com.keyconsultant.parse.logintutorial.model.user.authenticate.UserForgotPasswordErrorEvent;
import com.keyconsultant.parse.logintutorial.model.user.authenticate.UserForgotPasswordStartEvent;
import com.keyconsultant.parse.logintutorial.model.user.authenticate.UserForgotPasswordSuccessEvent;
import com.parse.Parse;
import com.squareup.otto.Subscribe;

/**
 * Activity which displays a login screen to the user, offering registration as
 * well. Based loosley on the default Login template. 
 * 
 * @author Trey Robinson
 */
public class LoginActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);


        Parse.initialize(this, "Your App Id", "Your Client ID");

        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.main_view, LoginFragment.newInstance());
        fragmentTransaction.commit();

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.activity_login, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle item selection
        switch (item.getItemId()) {
            case R.id.menu_forgot_password:
                forgotPassword();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    /**
     * Open the forgotPassword dialog 
     */
    private void forgotPassword(){
         FragmentManager fm = getSupportFragmentManager();
         ForgotPasswordDialogFragment forgotPasswordDialog = new ForgotPasswordDialogFragment();
         forgotPasswordDialog.show(fm, null);
    }


    @Subscribe
    public void onSignInStart(AuthenticateUserStartEvent event){
        showProgress(true, getString(R.string.login_progress_signing_in));
    }

    @Subscribe
    public void onSignInSuccess(AuthenticateUserSuccessEvent event){
        showProgress(false, getString(R.string.login_progress_signing_in));
        Intent loginSuccess = new Intent(this, MainActivity.class);
        startActivity(loginSuccess);
        finish();
    }

    @Subscribe
    public void onSignInError(AuthenticateUserErrorEvent event){
        showProgress(false, getString(R.string.login_progress_signing_in));
    }

    @Subscribe
    public void onForgotPasswordStart(UserForgotPasswordStartEvent event){
        showProgress(true, getString(R.string.login_progress_signing_in));
    }

    @Subscribe
    public void onForgotPasswordSuccess(UserForgotPasswordSuccessEvent event){
        showProgress(false,getString(R.string.login_progress_signing_in));
        Toast toast =Toast.makeText(this, "A password reset email has been sent.", Toast.LENGTH_LONG);
        toast.show();
    }

    @Subscribe
    public void onForgotPasswordError(UserForgotPasswordErrorEvent event){
        showProgress(false, getString(R.string.login_progress_signing_in));
        Toast toast =Toast.makeText(this, "An error has occured. Please try again.", Toast.LENGTH_LONG);
        toast.show();
    }
}

fragment_create_account

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    style="@style/LoginFormContainer" >

    <EditText
        android:id="@+id/etUsername"
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="25dp"
        android:hint="@string/usernameHint"
        android:inputType="text"
        android:maxLength="15" />

    <EditText
        android:id="@+id/etEmail"
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:layout_below="@id/etUsername"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="25dp"
        android:hint="@string/emailHint"
        android:inputType="textEmailAddress" />

    <EditText
        android:id="@+id/etPassword"
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:layout_below="@id/etEmail"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="25dp"
        android:hint="@string/passwordHint"
        android:inputType="textPassword"
        android:maxLength="10" />

    <EditText
        android:id="@+id/etPasswordConfirm"
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:layout_below="@id/etPassword"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="25dp"
        android:hint="@string/confirmPasswordHint"
        android:inputType="textPassword" />

    <Button
        android:id="@+id/btnCreateAccount"
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:layout_alignRight="@id/etPassword"
        android:layout_below="@id/etPasswordConfirm"
        android:layout_marginTop="25dp"
        android:text="@string/createAccount" />

</RelativeLayout>

CreateAccountFragment 类

package com.keyconsultant.parse.logintutorial;

import java.util.Locale;

import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;

import com.keyconsultant.parse.logintutorial.error.UnknownErrorDialogFactory;
import com.keyconsultant.parse.logintutorial.fragment.BaseFragment;
import com.keyconsultant.parse.logintutorial.model.user.UserManager;
import com.keyconsultant.parse.logintutorial.model.user.authenticate.AuthenticateUserErrorEvent;
import com.parse.ParseException;
import com.squareup.otto.Subscribe;

/**
 * Create an Account. Username is the primary method of login. Email is used for forgotten password recovery. 
 * 
 * @author Trey Robinson
 *
 */
public class CreateAccountFragment extends BaseFragment implements OnClickListener {

    protected static final String EXTRA_EMAIL = "com.keyconsultant.parse.logintutorial.fragment.extra.EMAIL";
    protected static final String EXTRA_USERNAME = "com.keyconsultant.parse.logintutorial.fragment.extra.USERNAME";
    protected static final String EXTRA_PASSWORD = "com.keyconsultant.parse.logintutorial.fragment.extra.PASSWORD";
    protected static final String EXTRA_CONFIRM = "com.keyconsultant.parse.logintutorial.fragment.extra.CONFIRMPASSWORD";

    private EditText mUserNameEditText;
    private EditText mEmailEditText; 
    private EditText mPasswordEditText;
    private EditText mConfirmPasswordEditText;
    private Button mCreateAccountButton;

    private String mEmail;
    private String mUsername;
    private String mPassword;
    private String mConfirmPassword;

    /**
     * Factory method for creating fragment instances.
     * @return
     */
    public static CreateAccountFragment newInstance(){
        return new CreateAccountFragment();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_create_account, container, false);

        mUserNameEditText = (EditText)view.findViewById(R.id.etUsername);
        mEmailEditText = (EditText)view.findViewById(R.id.etEmail);
        mPasswordEditText = (EditText)view.findViewById(R.id.etPassword);
        mConfirmPasswordEditText = (EditText)view.findViewById(R.id.etPasswordConfirm);

        mCreateAccountButton = (Button)view.findViewById(R.id.btnCreateAccount);
        mCreateAccountButton.setOnClickListener(this);
        return view;
    }


    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        if(savedInstanceState != null){
            mEmailEditText.setText(savedInstanceState.getString(EXTRA_EMAIL));
            mUserNameEditText.setText(savedInstanceState.getString(EXTRA_USERNAME));
            mPasswordEditText.setText(savedInstanceState.getString(EXTRA_PASSWORD));
            mConfirmPasswordEditText.setText(savedInstanceState.getString(EXTRA_CONFIRM));
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString(EXTRA_EMAIL, mEmailEditText.getText().toString());
        outState.putString(EXTRA_USERNAME, mUserNameEditText.getText().toString());
        outState.putString(EXTRA_PASSWORD, mPasswordEditText.getText().toString());
        outState.putString(EXTRA_CONFIRM, mConfirmPasswordEditText.getText().toString());
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.btnCreateAccount:
            createAccount();
            break;

        default:
            break;
        }
    }

    /**
     * Some front end validation is done that is not monitored by the service. 
     * If the form is complete then the information is passed to the service. 
     */
    private void createAccount(){
        clearErrors();

        boolean cancel = false;
        View focusView = null;

     // Store values at the time of the login attempt.
        mEmail = mEmailEditText.getText().toString();
        mUsername = mUserNameEditText.getText().toString();
        mPassword = mPasswordEditText.getText().toString();
        mConfirmPassword = mConfirmPasswordEditText.getText().toString();

        // Check for a valid confirm password.
        if (TextUtils.isEmpty(mConfirmPassword)) {
            mConfirmPasswordEditText.setError(getString(R.string.error_field_required));
            focusView = mConfirmPasswordEditText;
            cancel = true;
        } else if (mPassword != null && !mConfirmPassword.equals(mPassword)) {
            mPasswordEditText.setError(getString(R.string.error_invalid_confirm_password));
            focusView = mPasswordEditText;
            cancel = true;
        }
        // Check for a valid password.
        if (TextUtils.isEmpty(mPassword)) {
            mPasswordEditText.setError(getString(R.string.error_field_required));
            focusView = mPasswordEditText;
            cancel = true;
        } else if (mPassword.length() < 4) {
            mPasswordEditText.setError(getString(R.string.error_invalid_password));
            focusView = mPasswordEditText;
            cancel = true;
        }

        // Check for a valid email address.
        if (TextUtils.isEmpty(mEmail)) {
            mEmailEditText.setError(getString(R.string.error_field_required));
            focusView = mEmailEditText;
            cancel = true;
        } else if (!mEmail.contains("@")) {
            mEmailEditText.setError(getString(R.string.error_invalid_email));
            focusView = mEmailEditText;
            cancel = true;
        }

        if (cancel) {
            // There was an error; don't attempt login and focus the first
            // form field with an error.
            focusView.requestFocus();
        } else {
            // Show a progress spinner, and kick off a background task to
            // perform the user login attempt.
            UserManager.getInstance().signUp(mUsername.toLowerCase(Locale.getDefault()), mEmail, mPassword);

        }

    }

    /**
     * Remove error messages from all fields. 
     */
    private void clearErrors(){ mEmailEditText.setError(null);
        mUserNameEditText.setError(null);
        mPasswordEditText.setError(null);
        mConfirmPasswordEditText.setError(null);
    }

    @Subscribe
    public void onSignInError(AuthenticateUserErrorEvent event){
        clearErrors();
        switch (event.getErrorCode()) {
            case ParseException.INVALID_EMAIL_ADDRESS:
                mEmailEditText.setError(getString(R.string.error_invalid_email));
                mEmailEditText.requestFocus();
                break;
            case ParseException.EMAIL_TAKEN:
                mEmailEditText.setError(getString(R.string.error_duplicate_email));
                mEmailEditText.requestFocus();
                break;
            case ParseException.USERNAME_TAKEN:
                mUserNameEditText.setError(getString(R.string.error_duplicate_username));
                mUserNameEditText.requestFocus();
                break;
            default:
                UnknownErrorDialogFactory.createUnknownErrorDialog(this.getActivity()).show();
                break;
        }
    }

}
4

2 回答 2

0

设置你的线性布局android:layout_height="fill_parent"

我认为它会起作用。

于 2014-01-08T10:59:35.517 回答
0

添加另一个空视图作为最后一个孩子(紧跟在最后一个带有 id 的按钮之后register_button),如下所示。

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1" />

它将父LinearLayout视图延伸到整个高度。

于 2014-01-08T11:25:09.253 回答