شرح - تحميل برنامج android drawer
نفس جدول التنقل في الأنشطة المختلفة (8)
لقد قمت بعمل درج التنقل في العمل كما هو موضح في البرنامج التعليمي على موقع developer.android.com . ولكن الآن ، أريد استخدام درج تنقل واحد ، تم إنشاؤه في NavigationDrawer.class للأنشطة المتعددة في التطبيق الخاص بي.
سؤالي هو: إذا كان أي شخص هنا يمكنه إعداد برنامج تعليمي صغير ، وهو ما يفسر ، كيفية استخدام درج تنقل واحد لعدة أنشطة.
قرأته أولاً على هذا السؤال رد Android Navigation Drawer على أنشطة متعددة
لكنها لم تنجح في مشروعي
public class NavigationDrawer extends Activity {
public DrawerLayout drawerLayout;
public ListView drawerList;
private ActionBarDrawerToggle drawerToggle;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
drawerToggle = new ActionBarDrawerToggle((Activity) this, drawerLayout, R.drawable.ic_drawer, 0, 0) {
public void onDrawerClosed(View view) {
getActionBar().setTitle(R.string.app_name);
}
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(R.string.menu);
}
};
drawerLayout.setDrawerListener(drawerToggle);
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
layers = getResources().getStringArray(R.array.layers_array);
drawerList = (ListView) findViewById(R.id.left_drawer);
View header = getLayoutInflater().inflate(R.layout.drawer_list_header, null);
drawerList.addHeaderView(header, null, false);
drawerList.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, android.R.id.text1,
layers));
View footerView = ((LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(
R.layout.drawer_list_footer, null, false);
drawerList.addFooterView(footerView);
drawerList.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
map.drawerClickEvent(pos);
}
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (drawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
drawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
drawerToggle.onConfigurationChanged(newConfig);
}
}
في هذا النشاط ، أرغب في الحصول على درج التنقل حتى أقوم بتوسيع 'NavigationDrawer' وفي بعض الأنشطة الأخرى أريد أن أستخدم درج التنقل نفسه
public class SampleActivity extends NavigationDrawer {...}
لا أعرف ما يجب تغييره ...
أفعل ذلك في Kotlin مثل هذا:
open class BaseAppCompatActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
protected lateinit var drawerLayout: DrawerLayout
protected lateinit var navigationView: NavigationView
@Inject
lateinit var loginService: LoginService
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d("BaseAppCompatActivity", "onCreate()")
App.getComponent().inject(this)
drawerLayout = findViewById(R.id.drawer_layout) as DrawerLayout
val toolbar = findViewById(R.id.toolbar) as Toolbar
setSupportActionBar(toolbar)
navigationView = findViewById(R.id.nav_view) as NavigationView
navigationView.setNavigationItemSelectedListener(this)
val toggle = ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
toggle.isDrawerIndicatorEnabled = true
val navigationViewHeaderView = navigationView.getHeaderView(0)
navigationViewHeaderView.login_txt.text = SharedKey.username
}
private inline fun <reified T: Activity> launch():Boolean{
if(this is T) return closeDrawer()
val intent = Intent(applicationContext, T::class.java)
startActivity(intent)
finish()
return true
}
private fun closeDrawer(): Boolean {
drawerLayout.closeDrawer(GravityCompat.START)
return true
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
val id = item.itemId
when (id) {
R.id.action_tasks -> {
return launch<TasksActivity>()
}
R.id.action_contacts -> {
return launch<ContactActivity>()
}
R.id.action_logout -> {
createExitDialog(loginService, this)
}
}
return false
}
}
يجب أن ترث أنشطة الدرج هذه BaseAppCompatActivity
، استدعاء super.onCreate
بعد تعيين المحتوى (في الواقع ، يمكن نقلها إلى بعض الأسلوب init) ولها عناصر المقابلة لمعرفات في تخطيطها
إذا كنت تريد درج التنقل ، يجب عليك استخدام الأجزاء. لقد تابعت هذا البرنامج التعليمي الأسبوع الماضي وهو يعمل بشكل رائع:
http://developer.android.com/training/implementing-navigation/nav-drawer.html
يمكنك أيضًا تنزيل نموذج التعليمة البرمجية من هذا البرنامج التعليمي ، لمعرفة كيف يمكنك القيام بذلك.
بدون أجزاء:
هذا هو كود BaseActivity الخاص بك:
public class BaseActivity extends Activity
{
public DrawerLayout drawerLayout;
public ListView drawerList;
public String[] layers;
private ActionBarDrawerToggle drawerToggle;
private Map map;
protected void onCreate(Bundle savedInstanceState)
{
// R.id.drawer_layout should be in every activity with exactly the same id.
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
drawerToggle = new ActionBarDrawerToggle((Activity) this, drawerLayout, R.drawable.ic_drawer, 0, 0)
{
public void onDrawerClosed(View view)
{
getActionBar().setTitle(R.string.app_name);
}
public void onDrawerOpened(View drawerView)
{
getActionBar().setTitle(R.string.menu);
}
};
drawerLayout.setDrawerListener(drawerToggle);
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
layers = getResources().getStringArray(R.array.layers_array);
drawerList = (ListView) findViewById(R.id.left_drawer);
View header = getLayoutInflater().inflate(R.layout.drawer_list_header, null);
drawerList.addHeaderView(header, null, false);
drawerList.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, android.R.id.text1,
layers));
View footerView = ((LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(
R.layout.drawer_list_footer, null, false);
drawerList.addFooterView(footerView);
drawerList.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
map.drawerClickEvent(pos);
}
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (drawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
drawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
drawerToggle.onConfigurationChanged(newConfig);
}
}
يجب على جميع الأنشطة الأخرى التي تحتاج إلى الحصول على درج التنقل أن تمدد هذا النشاط بدلاً من النشاط نفسه ، مثال:
public class AnyActivity extends BaseActivity
{
//Because this activity extends BaseActivity it automatically has the navigation drawer
//You can just write your normal Activity code and you don't need to add anything for the navigation drawer
}
XML
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The main content view -->
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- Put what you want as your normal screen in here, you can also choose for a linear layout or any other layout, whatever you prefer -->
</FrameLayout>
<!-- The navigation drawer -->
<ListView android:id="@+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp"
android:background="#111"/>
</android.support.v4.widget.DrawerLayout>
تصحيح:
لقد واجهت بعض الصعوبات بنفسي ، لذا إليك الحل إذا حصلت على NullPointerExceptions. في BaseActivity تغيير الدالة onCreate إلى protected void onCreateDrawer()
. الباقي يمكن أن يبقى على حاله. في الأنشطة التي توسع BaseActivity ضع الرمز في هذا الترتيب:
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
super.onCreateDrawer();
هذا ساعدني على إصلاح مشكلتي ، آمل أن يساعد!
هذه هي الطريقة التي يمكنك بها إنشاء درج التنقل مع أنشطة متعددة ، إذا كان لديك أي أسئلة لا تتردد في طرحها.
تحرير 2:
كما قال BaseActivity
يمكنك أيضًا تجاوز setContentView()
واستدعاء onCreateDrawer هناك:
@Override
public void setContentView(@LayoutRes int layoutResID)
{
super.setContentView(layoutResID);
onCreateDrawer() ;
}
إنشاء درج التنقل في MainActivity الخاص بك باستخدام جزء.
تهيئة درج التنقل في MainActivity
الآن في جميع الأنشطة الأخرى التي تريد استخدامها ، استخدم Drawer Layer نفس DrawerLayout كقاعدة ومقطع كدرج ملاحة. ما عليك سوى تعيين android: اسم في الجزء الخاص بك يشير إلى ملف Java الخاص بك. لن تحتاج إلى تهيئة الجزء في الأنشطة الأخرى.
يمكنك الوصول إلى Nav Drawer عن طريق التمرير السريع في أنشطة أخرى مثل تطبيق Google Play Store
بالنسبة لأي شخص آخر يتطلع إلى القيام بما يطلبه الملصق الأصلي ، يرجى التفكير في استخدام الأجزاء بدلاً من الطريقة التي قالها كيفين. هنا هو تعليمي ممتاز حول كيفية القيام بذلك:
https://github.com/codepath/android_guides/wiki/Fragment-Navigation-Drawer
إذا اخترت بدلاً من ذلك استخدام الأنشطة بدلاً من الأجزاء ، فستواجه مشكلة إعادة إنشاء درج التنقل في كل مرة تنتقل فيها إلى نشاط جديد. وهذا يؤدي إلى عرض قبيح / بطيء لدرج التنقل في كل مرة.
لقد وجدت أفضل تنفيذ. إنه في تطبيق Google I / O 2014 .
انهم يستخدمون نفس النهج مثل كيفن. إذا تمكنت من تجريد نفسك من جميع العناصر غير الضرورية في تطبيق الإدخال / الإخراج ، فيمكنك استخراج كل ما تحتاج إليه وتأكد Google من أنه استخدام صحيح لنمط درج التنقل. كل نشاط يحتوي على DrawerLayout
اختياريًا DrawerLayout
الرئيسي. الجزء المثير للاهتمام هو كيف يتم التنقل إلى الشاشات الأخرى. يتم تنفيذه في BaseActivity
مثل هذا:
private void goToNavDrawerItem(int item) {
Intent intent;
switch (item) {
case NAVDRAWER_ITEM_MY_SCHEDULE:
intent = new Intent(this, MyScheduleActivity.class);
startActivity(intent);
finish();
break;
هذا يختلف عن الطريقة الشائعة لاستبدال الجزء الحالي بمعاملة جزء. لكن المستخدم لا يلاحظ أي فرق مرئي.
مع إجابةKevin van Mierlo ، أنت أيضًا قادر على تنفيذ عدة أدراج. على سبيل المثال ، يتم عرض القائمة الافتراضية الموجودة على الجانب الأيسر (بداية) ، وقائمة اختيارية أخرى ، على الجانب الأيمن ، والتي تظهر فقط عند تحديد الأجزاء.
لقد تمكنت من القيام بذلك.
أسهل طريقة لإعادة استخدام درج التنقل العام بين مجموعة من الأنشطة
app_base_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawer_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<FrameLayout
android:id="@+id/view_stub"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
<android.support.design.widget.NavigationView
android:id="@+id/navigation_view"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="@menu/menu_test"
/>
</android.support.v4.widget.DrawerLayout>
AppBaseActivity.java
/*
* This is a simple and easy approach to reuse the same
* navigation drawer on your other activities. Just create
* a base layout that conains a DrawerLayout, the
* navigation drawer and a FrameLayout to hold your
* content view. All you have to do is to extend your
* activities from this class to set that navigation
* drawer. Happy hacking :)
* P.S: You don't need to declare this Activity in the
* AndroidManifest.xml. This is just a base class.
*/
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.design.widget.NavigationView;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
public abstract class AppBaseActivity extends AppCompatActivity implements MenuItem.OnMenuItemClickListener {
private FrameLayout view_stub; //This is the framelayout to keep your content view
private NavigationView navigation_view; // The new navigation view from Android Design Library. Can inflate menu resources. Easy
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
private Menu drawerMenu;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.app_base_layout);// The base layout that contains your navigation drawer.
view_stub = (FrameLayout) findViewById(R.id.view_stub);
navigation_view = (NavigationView) findViewById(R.id.navigation_view);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, 0, 0);
mDrawerLayout.setDrawerListener(mDrawerToggle);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
drawerMenu = navigation_view.getMenu();
for(int i = 0; i < drawerMenu.size(); i++) {
drawerMenu.getItem(i).setOnMenuItemClickListener(this);
}
// and so on...
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
/* Override all setContentView methods to put the content view to the FrameLayout view_stub
* so that, we can make other activity implementations looks like normal activity subclasses.
*/
@Override
public void setContentView(int layoutResID) {
if (view_stub != null) {
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
View stubView = inflater.inflate(layoutResID, view_stub, false);
view_stub.addView(stubView, lp);
}
}
@Override
public void setContentView(View view) {
if (view_stub != null) {
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
view_stub.addView(view, lp);
}
}
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
if (view_stub != null) {
view_stub.addView(view, params);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Pass the event to ActionBarDrawerToggle, if it returns
// true, then it has handled the app icon touch event
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle your other action bar items...
return super.onOptionsItemSelected(item);
}
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.item1:
// handle it
break;
case R.id.item2:
// do whatever
break;
// and so on...
}
return false;
}
}
package xxxxxx;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.widget.SearchView;
import android.support.design.widget.NavigationView;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
public class loginhome extends AppCompatActivity {
private Toolbar toolbar;
private NavigationView navigationView;
private DrawerLayout drawerLayout;
// Make sure to be using android.support.v7.app.ActionBarDrawerToggle version.
// The android.support.v4.app.ActionBarDrawerToggle has been deprecated.
private ActionBarDrawerToggle drawerToggle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.loginhome);
// Initializing Toolbar and setting it as the actionbar
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//Initializing NavigationView
navigationView = (NavigationView) findViewById(R.id.nav_view);
//Setting Navigation View Item Selected Listener to handle the item click of the navigation menu
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
// This method will trigger on item Click of navigation menu
public boolean onNavigationItemSelected(MenuItem menuItem) {
//Checking if the item is in checked state or not, if not make it in checked state
if(menuItem.isChecked()) menuItem.setChecked(false);
else menuItem.setChecked(true);
//Closing drawer on item click
drawerLayout.closeDrawers();
//Check to see which item was being clicked and perform appropriate action
switch (menuItem.getItemId()){
//Replacing the main content with ContentFragment Which is our Inbox View;
case R.id.nav_first_fragment:
Toast.makeText(getApplicationContext(),"First fragment",Toast.LENGTH_SHORT).show();
FirstFragment fragment = new FirstFragment();
android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame,fragment);
fragmentTransaction.commit();
return true;
// For rest of the options we just show a toast on click
case R.id.nav_second_fragment:
Toast.makeText(getApplicationContext(),"Second fragment",Toast.LENGTH_SHORT).show();
SecondFragment fragment2 = new SecondFragment();
android.support.v4.app.FragmentTransaction fragmentTransaction2 = getSupportFragmentManager().beginTransaction();
fragmentTransaction2.replace(R.id.frame,fragment2);
fragmentTransaction2.commit();
return true;
default:
Toast.makeText(getApplicationContext(),"Somethings Wrong",Toast.LENGTH_SHORT).show();
return true;
}
}
});
// Initializing Drawer Layout and ActionBarToggle
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this,drawerLayout,toolbar,R.string.drawer_open, R.string.drawer_close){
@Override
public void onDrawerClosed(View drawerView) {
// Code here will be triggered once the drawer closes as we dont want anything to happen so we leave this blank
super.onDrawerClosed(drawerView);
}
@Override
public void onDrawerOpened(View drawerView) {
// Code here will be triggered once the drawer open as we dont want anything to happen so we leave this blank
super.onDrawerOpened(drawerView);
}
};
//Setting the actionbarToggle to drawer layout
drawerLayout.setDrawerListener(actionBarDrawerToggle);
//calling sync state is necessay or else your hamburger icon wont show up
actionBarDrawerToggle.syncState();
}
استخدم هذا لـ toolbar.xml الخاص بك
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:elevation="4dp"
android:id="@+id/toolbar"
android:theme="@style/ThemeOverlay.AppCompat.Dark"
>
</android.support.v7.widget.Toolbar>
استخدم هذا لرأس الملاحة إذا كنت تريد استخدامه
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="192dp"
android:background="?attr/colorPrimaryDark"
android:padding="16dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark"
android:orientation="vertical"
android:gravity="bottom">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="56dp"
android:id="@+id/navhead"
android:orientation="vertical"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true">
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:textColor="#ffffff"
android:text="tanya"
android:textSize="14sp"
android:textStyle="bold"
/>
<TextView
android:id="@+id/email"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:layout_marginLeft="16dp"
android:layout_marginTop="5dp"
android:text="tanya.com"
android:textSize="14sp"
android:textStyle="normal"
/>
</LinearLayout>
<de.hdodenhof.circleimageview.CircleImageView
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_below="@+id/imageView"
android:layout_marginTop="15dp"
android:src="@drawable/face"
android:id="@+id/circleView"
/>
</RelativeLayout>