ELs dashboard d'Android és un element important dins de les aplicacions Android, ja que proporciona una navegació fàcil dins de totes les funcionalitats que ofereix una aplició.
Android dona suport a milions de dispositius
Realitzarem el tutorial que trobem dins de la següent pàgina, per a crear un dashboard d'una aplicació.
http://www.androidhive.info/2011/12/android-dashboard-design-tutorial/
Rescriurem el fitxer styles.xml que podrem trobar dins de la carpeta /res/values.
<resources> <style name="ActionBarCompat"> <item name="android:layout_width">fill_parent</item> <item name="android:layout_height">50dp</item> <item name="android:orientation">horizontal</item> <item name="android:background">@drawable/actionbar_background</item> </style> <style name="DashboardButton"> <item name="android:layout_gravity">center_vertical</item> <item name="android:layout_width">wrap_content</item> <item name="android:layout_height">wrap_content</item> <item name="android:gravity">center_horizontal</item> <item name="android:drawablePadding">2dp</item> <item name="android:textSize">16dp</item> <item name="android:textStyle">bold</item> <item name="android:textColor">#FFFFFF</item> <item name="android:background">@null</item> </style> <style name="FooterBar"> <item name="android:layout_width">fill_parent</item> <item name="android:layout_height">40dp</item> <item name="android:orientation">horizontal</item> <item name="android:background">#dedede</item> </style> </resources>
Crearem dos imatges una per al fons del action bar i logo.
Afegirem un nou fitxer xml dins de /res/layout de nom actionbar_layout i el dixarem amb el contingut següent.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" style="@style/ActionBarCompat" > <ImageView android:layout_width="wrap_content" android:layout_height="fill_parent" android:clickable="false" android:paddingLeft="15dip" android:scaleType="center" android:src="@drawable/facebook_logo" /> </LinearLayout>
Seleccionarem les diferents icones que volem utilitzar amb la nostra aplicació podem utilitzar les nostres propies creant-les amb qualsevol programa d'edició fotogràfica com pot ser el photoshop o el gimp.
Crearem una nova classe de java de amb el següent nom DashboardLayout.java i contingut
public class DashboardLayout extends ViewGroup { private static final int UNEVEN_GRID_PENALTY_MULTIPLIER = 10; private int mMaxChildWidth = 0; private int mMaxChildHeight = 0; public DashboardLayout(Context context) { super(context, null); } public DashboardLayout(Context context, AttributeSet attrs) { super(context, attrs, 0); } public DashboardLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { mMaxChildWidth = 0; mMaxChildHeight = 0; // Measure once to find the maximum child size. int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST); int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST); final int count = getChildCount(); for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() == GONE) { continue; } child.measure(childWidthMeasureSpec, childHeightMeasureSpec); mMaxChildWidth = Math.max(mMaxChildWidth, child.getMeasuredWidth()); mMaxChildHeight = Math.max(mMaxChildHeight, child.getMeasuredHeight()); } // Measure again for each child to be exactly the same size. childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( mMaxChildWidth, MeasureSpec.EXACTLY); childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( mMaxChildHeight, MeasureSpec.EXACTLY); for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() == GONE) { continue; } child.measure(childWidthMeasureSpec, childHeightMeasureSpec); } setMeasuredDimension( resolveSize(mMaxChildWidth, widthMeasureSpec), resolveSize(mMaxChildHeight, heightMeasureSpec)); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int width = r - l; int height = b - t; final int count = getChildCount(); // Calculate the number of visible children. int visibleCount = 0; for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() == GONE) { continue; } ++visibleCount; } if (visibleCount == 0) { return; } // Calculate what number of rows and columns will optimize for even horizontal and // vertical whitespace between items. Start with a 1 x N grid, then try 2 x N, and so on. int bestSpaceDifference = Integer.MAX_VALUE; int spaceDifference; // Horizontal and vertical space between items int hSpace = 0; int vSpace = 0; int cols = 1; int rows; while (true) { rows = (visibleCount - 1) / cols + 1; hSpace = ((width - mMaxChildWidth * cols) / (cols + 1)); vSpace = ((height - mMaxChildHeight * rows) / (rows + 1)); spaceDifference = Math.abs(vSpace - hSpace); if (rows * cols != visibleCount) { spaceDifference *= UNEVEN_GRID_PENALTY_MULTIPLIER; } if (spaceDifference < bestSpaceDifference) { // Found a better whitespace squareness/ratio bestSpaceDifference = spaceDifference; // If we found a better whitespace squareness and there's only 1 row, this is // the best we can do. if (rows == 1) { break; } } else { // This is a worse whitespace ratio, use the previous value of cols and exit. --cols; rows = (visibleCount - 1) / cols + 1; hSpace = ((width - mMaxChildWidth * cols) / (cols + 1)); vSpace = ((height - mMaxChildHeight * rows) / (rows + 1)); break; } ++cols; } // Lay out children based on calculated best-fit number of rows and cols. // If we chose a layout that has negative horizontal or vertical space, force it to zero. hSpace = Math.max(0, hSpace); vSpace = Math.max(0, vSpace); // Re-use width/height variables to be child width/height. width = (width - hSpace * (cols + 1)) / cols; height = (height - vSpace * (rows + 1)) / rows; int left, top; int col, row; int visibleIndex = 0; for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() == GONE) { continue; } row = visibleIndex / cols; col = visibleIndex % cols; left = hSpace * (col + 1) + width * col; top = vSpace * (row + 1) + height * row; child.layout(left, top, (hSpace == 0 && col == cols - 1) ? r : (left + width), (vSpace == 0 && row == rows - 1) ? b : (top + height)); ++visibleIndex; } } }
Ara crearem el fitxer que contindrà el layout del dashboard com en els anteriors layouts o crearem dins de la carpeta /res/layout el nom que li donarem al fitxer serà fragment_layout.xml.
<com.androidhive.dashboard.DashboardLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" android:background="#008080" > <!-- News Feed Button --> <Button android:id="@+id/btn_news_feed" style="@style/DashboardButton" android:drawableTop="@drawable/btn_newsfeed" android:text="News Feed" /> <!-- Friends Button --> <Button android:id="@+id/btn_friends" style="@style/DashboardButton" android:drawableTop="@drawable/ic_action_add_person" android:text="Friends" /> <!-- Messages Button --> <Button android:id="@+id/btn_messages" style="@style/DashboardButton" android:drawableTop="@drawable/ic_messages_default" android:text="Messages" /> <!-- Places Button --> <Button android:id="@+id/btn_places" style="@style/DashboardButton" android:drawableTop="@drawable/btn_places" android:text="Places" /> <!-- Events Button --> <Button android:id="@+id/btn_events" style="@style/DashboardButton" android:drawableTop="@drawable/ic_hardware_phone" android:text="Events" /> <!-- Photos Button --> <Button android:id="@+id/btn_photos" style="@style/DashboardButton" android:drawableTop="@drawable/btn_photos" android:text="Photos" /> </com.androidhive.dashboard.DashboardLayout>
Ara crearem un nou fitxer que contindrà el peu de l'aplicació. Li donarem el nom de footer_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" style="@style/FooterBar" > <TextView android:text="www.facebook.com" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="#606060" android:gravity="center" android:paddingTop="10dip"/> </LinearLayout>
Fins ara hem dissenyat la Action Bar, Dashboard i peu de pàgina. Finalment hem de combinar tots els dissenys en un arxiu xml. dashboard_layout.xml.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/home_root" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <!-- Include Action Bar --> <include layout="@layout/actionbar_layout"/> <!-- Include Fragmented dashboard --> <include layout="@layout/fragment_layout"/> <!-- Include Footer --> <include layout="@layout/footer_layout"/> </LinearLayout>
Fins ara, hem creat un panell estàtic que no té funcionalitat total. Així que hem d'afegir algunes funcions com el llançament de les activitats independents per a cada icona en el dashboard. En aquest cas les 6 icones del panell de control, així que necessitem 6 Activitats un per a cada icona.
Obrim el fitxer de classe activitat principal i copiem el codi següent. ( AndroidDashboardDesignActivity.java)
public class AndroidDashboardDesignActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.dashboard_layout); /** * Creating all buttons instances * */ // Dashboard News feed button Button btn_newsfeed = (Button) findViewById(R.id.btn_news_feed); // Dashboard Friends button Button btn_friends = (Button) findViewById(R.id.btn_friends); // Dashboard Messages button Button btn_messages = (Button) findViewById(R.id.btn_messages); // Dashboard Places button Button btn_places = (Button) findViewById(R.id.btn_places); // Dashboard Events button Button btn_events = (Button) findViewById(R.id.btn_events); // Dashboard Photos button Button btn_photos = (Button) findViewById(R.id.btn_photos); /** * Handling all button click events * */ // Listening to News Feed button click btn_newsfeed.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // Launching News Feed Screen Intent i = new Intent(getApplicationContext(), NewsFeedActivity.class); startActivity(i); } }); // Listening Friends button click btn_friends.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // Launching News Feed Screen Intent i = new Intent(getApplicationContext(), FriendsActivity.class); startActivity(i); } }); // Listening Messages button click btn_messages.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // Launching News Feed Screen Intent i = new Intent(getApplicationContext(), MessagesActivity.class); startActivity(i); } }); // Listening to Places button click btn_places.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // Launching News Feed Screen Intent i = new Intent(getApplicationContext(), PlacesActivity.class); startActivity(i); } }); // Listening to Events button click btn_events.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // Launching News Feed Screen Intent i = new Intent(getApplicationContext(), EventsActivity.class); startActivity(i); } }); // Listening to Photos button click btn_photos.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // Launching News Feed Screen Intent i = new Intent(getApplicationContext(), PhotosActivity.class); startActivity(i); } }); } }
Crearem una nova activitat que ens farà que sigui funcional el botó news feed el nom de la classe serà NewsfeedsActivty.java
public class NewsFeedActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.news_feed_layout); } }
Farem el mateix per a totes les activitats que tenim associades a cada un dels nostres botons.
Per a cada una de les activitats també crearem el seu diferent layout una mostra del que haurem de realitzar serà crear el layout associat a la nostra activitat NewsfeedsActivty el fitxer associat serà news_feed_layout.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#f8f9fe" android:orientation="vertical" > <include layout="@layout/actionbar_layout" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="15dip" android:text="News Feed Screen" android:textColor="#ff29549f" android:textSize="25dip" android:textStyle="bold" /> </LinearLayout> </LinearLayout>
No ens podem oblidar tampoc si volem que la nostra aplicació funcioni de modificar el fitxer de Manifest afegint-li les diferents activitats.
<application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:label="@string/app_name" android:name="com.androidhive.dashboard.AndroidDashboardDesignActivity" > <intent-filter > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- News Feed Activity --> <activity android:name="com.androidhive.dashboard.NewsFeedActivity" ></activity> <!-- Friends Activity --> <activity android:name="com.androidhive.dashboard.FriendsActivity" ></activity> <!-- Messages Activity --> <activity android:name="com.androidhive.dashboard.MessagesActivity" ></activity> <!-- Places Activity --> <activity android:name="com.androidhive.dashboard.PlacesActivity" ></activity> <!-- Events Activity --> <activity android:name="com.androidhive.dashboard.EventsActivity" ></activity> <!-- Photos Activity --> <activity android:name="com.androidhive.dashboard.PhotosActivity" ></activity> </application>
Podeu trobar el projecte a la següent direcció. https://github.com/jordiromero/androiddashboard
http://android-ui-utils.googlecode.com/hg/asset-studio/dist/index.html