片段 - 如何将它们与需要操作的活动一起使用?
Posted
技术标签:
【中文标题】片段 - 如何将它们与需要操作的活动一起使用?【英文标题】:fragments - how to use them with activities that require actions? 【发布时间】:2015-04-21 22:16:30 【问题描述】:首先 - 为新手问题道歉。
我正在尝试实现将在我的应用程序中使用的导航抽屉。首先,我按照 android 教程创建了一个基本导航,它使用 Fragments 更改 a。
我可以将框架布局 ID 和片段传递给 FragmentTransaction。它工作得很好。
我决定使用默认的 android 文件创建一个新的登录活动(在 Android Studio 中:转到新的 - 活动 - 登录活动)。这让我感到困惑。我的问题是:
我可以创建登录活动的片段,其中 LoginActivity 中的操作将起作用吗?看起来fragment会根据传递的布局创建视图,但是LoginActivity中使用的方法不起作用?
如果创建片段不适用于登录活动,那么在切换活动时确保导航正常工作的最简洁方法是什么? Navigation Drawer 仅在主要活动上有效;切换到其他活动(通过 Intent)会导致应用丢失导航抽屉操作。操作栏/导航抽屉的图像仍然存在。
这是我在 MainActivity 中的一些代码......也许我遗漏了一些导致导航抽屉在 Intent 切换活动时停止运行的东西?
(注意:LoginActivity 扩展了 LoginActivity 类中的 MainActivity)
提前感谢您的任何指导/建议!
public class MainActivity extends ActionBarActivity
private NavigationDrawerFragment mNavigationDrawerFragment;
//USER DATA
public String mUserID;
public String mToken;
public String mProgramData;
//NAVIGATION DRAWER
private CharSequence mTitle;
private CharSequence mDrawerTitle;
private String[] mTitles;
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
private ActionBarDrawerToggle mActionBarDrawerToggle;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTitle = mDrawerTitle = getTitle();
// get list items for nav
mTitles = getResources().getStringArray(R.array.nav_menu);
//drawer widget
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
//listview of left drawer
mDrawerList = (ListView) findViewById(R.id.left_drawer);
// Set up the drawer.
mDrawerList.setAdapter(new ArrayAdapter<>(this,
R.layout.drawer_list_item, mTitles));
//set onclicklistener on the each list item of menu options
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
// some styling...
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
//enables action bar app behavior
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// ties drawerlayout and actionbar for navigation drawers
mActionBarDrawerToggle = new ActionBarDrawerToggle(
this,
mDrawerLayout,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close)
// different titles for the drawer actions
public void onDrawerClosed(View drawerView)
getSupportActionBar().setTitle(mTitle);
public void onDrawerOpened(View drawerView)
getSupportActionBar().setTitle(mDrawerTitle);
;
// set drawer toggle as the drawer listener
mDrawerLayout.setDrawerListener(mActionBarDrawerToggle);
private class DrawerItemClickListener implements ListView.OnItemClickListener
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
selectItem(position);
@Override
protected void onPostCreate(Bundle savedInstanceState)
super.onPostCreate(savedInstanceState);
mActionBarDrawerToggle.syncState();
@Override
public void onConfigurationChanged(Configuration newConfig)
super.onConfigurationChanged(newConfig);
mActionBarDrawerToggle.onConfigurationChanged(newConfig);
@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 (mActionBarDrawerToggle.onOptionsItemSelected(item))
return true;
switch(id)
case R.id.action_home:
Intent home = new Intent(this, MainActivity.class);
this.startActivity(home);
break;
case R.id.action_login:
Intent login = new Intent(this, LoginActivity.class);
this.startActivity(login);
break;
return super.onOptionsItemSelected(item);
编辑
感谢您迄今为止在指导我解决问题方面的帮助。 不幸的是,我认为我问的问题不正确,但也许从 Android Studio 查看 LoginActivity 代码会有所帮助。
这是 LoginActivity 的一部分:
public class LoginActivity extends MainActivity implements LoaderCallbacks<Cursor>
private UserLoginTask mAuthTask = null;
// UI references.
private AutoCompleteTextView mUserIDView;
private EditText mPasswordView;
private View mProgressView;
private View mLoginFormView;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
// Set up the login form.
mUserIDView = (AutoCompleteTextView) findViewById(R.id.email);
populateAutoComplete();
mPasswordView = (EditText) findViewById(R.id.password);
mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener()
@Override
public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent)
if (id == R.id.login || id == EditorInfo.IME_NULL)
attemptLogin();
return true;
return false;
);
Button mEmailSignInButton = (Button) findViewById(R.id.email_sign_in_button);
mEmailSignInButton.setOnClickListener(new OnClickListener()
@Override
public void onClick(View view)
attemptLogin();
);
mLoginFormView = findViewById(R.id.login_form);
mProgressView = findViewById(R.id.login_progress);
private void populateAutoComplete()
getLoaderManager().initLoader(0, null, this);
/**
* 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()
if (mAuthTask != null)
return;
// Reset errors.
mUserIDView.setError(null);
mPasswordView.setError(null);
// Store values at the time of the login attempt.
String email = mUserIDView.getText().toString();
String password = mPasswordView.getText().toString();
boolean cancel = false;
View focusView = null;
// Check for a valid password, if the user entered one.
if (TextUtils.isEmpty(password))
mPasswordView.setError(getString(R.string.error_invalid_password));
focusView = mPasswordView;
cancel = true;
// Check for a valid email address or ID.
if (TextUtils.isEmpty(email))
mUserIDView.setError(getString(R.string.error_field_required));
focusView = mUserIDView;
cancel = true;
else if (!isEmailValid(email) && !isIDValid(email))
mUserIDView.setError(getString(R.string.error_invalid_email));
focusView = mUserIDView;
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.
showProgress(true);
mAuthTask = new UserLoginTask(email, password);
mAuthTask.execute((Void) null);
private boolean isEmailValid(String email)
//TODO: Replace this with your own logic
return email.contains("@");
private boolean isIDValid(String email)
//TODO: Replace this with your own logic
return email.length() == 6;
[continued]...........
我将创建一个名为 menu1_Fragment 的简单 LoginActivity 片段:
public class menu1_Fragment extends android.support.v4.app.Fragment
View rootview;
public View onCreateView(LayoutInflater inflater, ViewGroup view, Bundle savedInstanceState)
rootview = (ViewGroup)inflater.inflate(R.layout.activity_login, null);
return rootview;
如果我是正确的(希望我错了!)片段将替换为视图(menu1_Fragment)。 View 不能有动作(比如点击登录按钮发送 httppost 请求)。
另外,您能否解释一下为什么 MainActivity 中的 onOptionsItemSelected 会破坏导航抽屉(抽屉变得不可点击。也无法向右滑动以将其拉起)。 Intent 启动一个活动(LoginActivity),但只有抽屉在外观上显示。
【问题讨论】:
【参考方案1】:要隐藏ActionBar
图标,您可以这样做:
@Override
public boolean onOptionsItemSelected(MenuItem item)
// toggle nav drawer on selecting action bar app icon/title
if (mDrawerToggle.onOptionsItemSelected(item))
return true;
// Handle action bar actions click
switch (item.getItemId())
case R.id.action_settings:
return true;
default:
return super.onOptionsItemSelected(item);
到replace
main fragment
当您单击drawable menu list
中的项目时,我看到您使用了selectItem(position)
方法,但是该方法从未在您的代码中声明。为此,您也可以执行以下操作:
private void selectItem(int position)
// update the main content by replacing fragments
Fragment fragment = null;
switch (position)
case 1:
fragment = new TestFragment();
break;
case 2:
fragment = new TestFragment2();
break;
default:
break;
if (fragment != null)
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
// update selected item and title, then close the drawer
setTitle(navMenuTitles[position]);
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(position);
mDrawerLayout.closeDrawer(mDrawerList);
else
// error in creating fragment
Log.e("MainActivity", "Error in creating fragment");
【讨论】:
感谢您迄今为止的帮助。我已经更新了我的问题,希望能更好地解释我想要做什么..【参考方案2】:我正在给您一个示例,其中定义为片段并使用 MainActivity 调用的多个活动,希望您能从中获得解决方案..
MainActivity.java
package com.example.fragmentdemo1;
import java.util.ArrayList;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.ActionBarActivity;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity implements
OnItemClickListener
MainActivity activity;
private ListView lv;
private ArrayList<String> list = new ArrayList<String>();
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
activity = this;
lv = (ListView) findViewById(R.id.listView);
list.add("First");
list.add("Second");
list.add("Third");
list.add("Forth");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(activity,
android.R.layout.simple_list_item_1, list);
lv.setAdapter(adapter);
lv.setOnItemClickListener(this);
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id)
switch (position)
case 0:
Fragment1 f1 = new Fragment1();
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.addToBackStack(null);
transaction.replace(R.id.container, f1).commit();
break;
case 1:
Fragment2 f2 = new Fragment2();
FragmentTransaction transaction2 = getSupportFragmentManager()
.beginTransaction();
transaction2.addToBackStack(null);
transaction2.replace(R.id.container, f2).commit();
break;
case 2:
Toast.makeText(activity, "" + position, 1000).show();
Fragment3 f3 = new Fragment3();
FragmentTransaction transaction3 = getSupportFragmentManager()
.beginTransaction();
transaction3.addToBackStack(null);
transaction3.replace(R.id.container, f3).commit();
break;
case 3:
Fragment4 f4 = new Fragment4();
FragmentTransaction transaction4 = getSupportFragmentManager()
.beginTransaction();
transaction4.addToBackStack(null);
transaction4.replace(R.id.container, f4).commit();
break;
default:
break;
@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();
switch (id)
case android.R.id.home:
finish();
break;
default:
break;
return false;
Fragment1.java
package com.example.fragmentdemo1;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class Fragment1 extends android.support.v4.app.Fragment
TextView tv;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup view,
Bundle savedInstanceState)
tv =(TextView)view.findViewById(R.id.textView1);
view = (ViewGroup) inflater.inflate(R.layout.fragment1, null);
return view;
Fragment2.java
package com.example.fragmentdemo1;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class Fragment2 extends Fragment
TextView tv;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup view,
Bundle savedInstanceState)
tv =(TextView)view.findViewById(R.id.textView2);
view = (ViewGroup) inflater.inflate(R.layout.fragment2, null);
return view;
Fragment3.java
package com.example.fragmentdemo1;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class Fragment3 extends Fragment
TextView tv;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup view,
Bundle savedInstanceState)
tv =(TextView)view.findViewById(R.id.textView3);
view =(ViewGroup)inflater.inflate(R.layout.fragment3, null);
return view;
Fragment4.java
package com.example.fragmentdemo1;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class Fragment4 extends Fragment
TextView tv;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup view,
Bundle savedInstanceState)
tv =(TextView)view.findViewById(R.id.textView4);
view = (ViewGroup)inflater.inflate(R.layout.fragment4, null);
return view;
注意:如果你想使用从 Fragment 类到 MainActivity 的方法,那么你可以将它设为 public static
,你可以直接使用该方法的类名,如 Fragment1.countData()
。
此演示也适用于导航抽屉。
【讨论】:
感谢到目前为止的帮助,但我认为我并不完全清楚。我已经更新了这个问题,希望能帮助我更好地了解我的需求。以上是关于片段 - 如何将它们与需要操作的活动一起使用?的主要内容,如果未能解决你的问题,请参考以下文章
Android:将 savedInstanceState 与片段一起使用
Android Studio - 选项卡式活动如何将片段重置为默认视图?