إنشاء صفحة onBoarding في الاندرويد ستوديو وحفظ القيمة داخل sharedPreferences
في هذا الدرس نقوم لكم الصفحة الاكثر استخداما وهي الonboarding وهي بكل بساطة عباره عن صفحة بسيطة جدا تظهر للمره الاولى لاستخدام التطبيق وبعد استخدام هذه الصفحة والانتهاء من اخر صفحة سيتم حفظ قيمة الصفحة في ال Preferences ولن تظهر مرى اخرى الا في حالة حذف الcache الخاصه بالتطبيق من الجهاز وغالبا ما نشاهد ظهور هذه الصفحة في الكثير من التطبيقات المشهوره وذلك بسبب جمالها وتوضيحها لفكرة التطبيق .
تطبيق الهاتف المحمول الأصلي مكتوب باللغة الأم للهاتف الذكي. على سبيل المثال ، Java لنظام Android و Swift لنظام iOS ، أو Flutter ، والتي يمكن استخدامها على كلا النظامين الأساسيين!
الوسيلة الأكثر شيوعًا اليوم هي التطبيقات المحلية. هذه هي تطبيقات الهاتف المحمول التي تم إنشاؤها خصيصًا لنظام تشغيل معين (iOS أو Android). لن يعمل التطبيق الذي تم إنشاؤه لنظام Android على نظام التشغيل iOS ، والعكس صحيح. نظرًا لأن كل نظام تشغيل له مجموعته الخاصة من الرموز والخصائص ، فإن تطوير تطبيق محلي يستغرق وقتًا أطول ، ويكون أكثر تعقيدًا ، وبالتالي يكلف أكثر. نتيجة لذلك ، إذا كنت ترغب في نشر نفس تطبيق الهاتف المحمول على نظامي التشغيل المنفصلين ، فستحتاج إلى تصميمه مرتين. عندما تختار تطبيقًا محليًا ، يمكنك أن تطمئن إلى أنه سيكون ذا جودة عالية جدًا لأنه تم إنشاؤه خصيصًا لك.
google console play console android android studio mac android studio krita android
الملقحات التي تحتاج اليها
قم بتحميل الملف التالي وفك الاستخراج عنه وبعدها قم بنسخ الملفات التي بداخلها ولصقها بداخل الdrawable لكي لا يحدث معك مشاكل اثناء العملية .
image.rar
يمكنك تحميل الملحقات من هنا | او من هنا
الالوان التي نحتاج اليها في التصميم
قم بإضافة الالوان التاليه في الملف المخصص للالوان لانك سوف تحتاج اليها ويمكنك استبدال الالوان باي الوان اخرى تريد التعامل معها .
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#F61313</color>
<color name="purple_700">#400A0A</color>
<color name="teal_200">#FF9800</color>
<color name="teal_700">#E91E63</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="tab_indicator_gray">#E38C8E</color>
<color name="intro_title_color">#EB5B5F</color>
<color name="intro_description_color">#656565</color>
<color name="MainPrimary">#E3B7A0</color>
الثيم الذي سوف نعمل عليه
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.MyApplication" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/MainPrimary</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<item name="android:textColor" > @color/white </item>
<!-- Customize your theme here. -->
</style>
</resources>
الانميشن الذي سوف نقوم بعمل على زر get started
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="500" />
<translate
android:fromYDelta="-100%"
android:toYDelta="0%"
android:duration="700" />
</set>
التصميم الذي سوف نقوم بتغييره اثناء عملية التنقل بين الصفحات
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.56882256" />
<TextView
android:id="@+id/intro_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="8dp"
android:text="TextView"
android:textColor="@color/MainPrimary"
android:textSize="32dp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/guideline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline" />
<TextView
android:lineSpacingExtra="16dp"
android:id="@+id/intro_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:layout_marginBottom="8dp"
android:text="TextView"
android:textColor="#676767"
android:textAlignment="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/intro_title"
app:layout_constraintVertical_bias="0.13" />
<ImageView
android:id="@+id/intro_img"
android:layout_width="wrap_content"
android:layout_height="222dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="32dp"
app:layout_constraintBottom_toTopOf="@+id/intro_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:srcCompat="@tools:sample/backgrounds/scenic" />
</androidx.constraintlayout.widget.ConstraintLayout>
تهيئة adapter لتغيير الصفحات اثناء عملية التنقل
public class IntroViewPagerAdapter extends PagerAdapter {
Context mContext ;
List<ScreenItem> mListScreen;
public IntroViewPagerAdapter(Context mContext, List<ScreenItem> mListScreen) {
this.mContext = mContext;
this.mListScreen = mListScreen;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layoutScreen = inflater.inflate(R.layout.layout_screen,null);
ImageView imgSlide = layoutScreen.findViewById(R.id.intro_img);
TextView title = layoutScreen.findViewById(R.id.intro_title);
TextView description = layoutScreen.findViewById(R.id.intro_description);
title.setText(mListScreen.get(position).getTitle());
description.setText(mListScreen.get(position).getDescription());
imgSlide.setImageResource(mListScreen.get(position).getScreenImg());
container.addView(layoutScreen);
return layoutScreen;
}
@Override
public int getCount() {
return mListScreen.size();
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object o) {
return view == o;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView((View)object);
}
}
تصميم الصفحة الرئيسيه التي يعمل عليها التصميم
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.viewpager.widget.ViewPager
android:id="@+id/screen_viewpager"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toTopOf="@+id/tab_indicator"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:layout_marginBottom="16dp"
android:drawableRight="@drawable/ic_arrow_forward_black_24dp"
android:text="Next"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@drawable/menuback"
app:layout_constraintEnd_toEndOf="parent" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/btn_next"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:tabBackground="@drawable/indicator_selector">
</com.google.android.material.tabs.TabLayout>
<Button
android:visibility="invisible"
android:id="@+id/btn_get_started"
android:layout_width="132dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="64dp"
android:background="@drawable/menuback"
android:text="Get Started"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:textSize="16sp"
android:textStyle="bold"
android:textColor="@color/MainPrimary"
android:id="@+id/tv_skip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginEnd="24dp"
android:layout_marginRight="24dp"
android:text="Skip"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
إنشاء DataModel للسماح بتغيير البيانات اثناء عمليات التنقل
public class ScreenItem {
String Title,Description;
int ScreenImg;
public ScreenItem(String title, String description, int screenImg) {
Title = title;
Description = description;
ScreenImg = screenImg;
}
public void setTitle(String title) {
Title = title;
}
public void setDescription(String description) {
Description = description;
}
public void setScreenImg(int screenImg) {
ScreenImg = screenImg;
}
public String getTitle() {
return Title;
}
public String getDescription() {
return Description;
}
public int getScreenImg() {
return ScreenImg;
}
}
الاكواد المسؤوله عن عملية الانتقال من صفحة للاخرى وتغيير البيانات
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout;
import java.util.ArrayList;
import java.util.List;
public class OnBoarding extends AppCompatActivity {
private ViewPager screenPager;
IntroViewPagerAdapter introViewPagerAdapter ;
TabLayout tabIndicator;
Button btnNext;
int position = 0 ;
Button btnGetStarted;
Animation btnAnim ;
TextView tvSkip;
Boolean visible = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// after open every Time.
if (restorePrefData()) {
Intent mainActivity = new Intent(getApplicationContext(),CheckBox.class );
startActivity(mainActivity);
finish();
}
setContentView(R.layout.activity_on_boarding);
// hide the action bar
getSupportActionBar().hide();
// ini views
btnNext = findViewById(R.id.btn_next);
btnGetStarted = findViewById(R.id.btn_get_started);
tabIndicator = findViewById(R.id.tab_indicator);
btnAnim = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.anim);
tvSkip = findViewById(R.id.tv_skip);
// fill list screen
final List<ScreenItem> mList = new ArrayList<>();
mList.add(new ScreenItem("-------------------------","Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua, consectetur consectetur adipiscing elit",R.drawable.img1));
mList.add(new ScreenItem("-------------------------","Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua, consectetur consectetur adipiscing elit",R.drawable.img2));
mList.add(new ScreenItem("-------------------------","Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua, consectetur consectetur adipiscing elit",R.drawable.img3));
// setup viewpager
screenPager =findViewById(R.id.screen_viewpager);
introViewPagerAdapter = new IntroViewPagerAdapter(this,mList);
screenPager.setAdapter(introViewPagerAdapter);
// setup tablayout with viewpager
tabIndicator.setupWithViewPager(screenPager);
// next button click Listner
btnNext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
position = screenPager.getCurrentItem();
if (position < mList.size()) {
position++;
screenPager.setCurrentItem(position);
}
if (position == mList.size()-1) { // when we rech to the last screen
loaddLastScreen();
}
}
});
// tablayout add change listener
tabIndicator.addOnTabSelectedListener(new TabLayout.BaseOnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
if (tab.getPosition() == mList.size()-1) {
loaddLastScreen();
}
else if (visible == true)
{
btnNext.setVisibility(View.VISIBLE);
btnGetStarted.setVisibility(View.INVISIBLE);
tvSkip.setVisibility(View.VISIBLE);
tabIndicator.setVisibility(View.VISIBLE);
visible = false;
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
// Get Started button click listener
btnGetStarted.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// after end directly
Intent mainActivity = new Intent(getApplicationContext(),CheckBox.class);
startActivity(mainActivity);
savePrefsData();
finish();
}
});
// skip button click listener
tvSkip.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
screenPager.setCurrentItem(mList.size());
}
});
}
private boolean restorePrefData() {
SharedPreferences pref = getApplicationContext().getSharedPreferences("myPrefs",MODE_PRIVATE);
boolean isIntroActivityOpnendBefore = pref.getBoolean("isIntroOpnend",false);
return isIntroActivityOpnendBefore;
}
private void savePrefsData() {
SharedPreferences pref = getApplicationContext().getSharedPreferences("onBoarding",MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putBoolean("isIntroOpnend",true);
editor.commit();
}
// show the GET_STARTED Button and hide the indicator and the next button
private void loaddLastScreen() {
btnNext.setVisibility(View.INVISIBLE);
btnGetStarted.setVisibility(View.VISIBLE);
tvSkip.setVisibility(View.INVISIBLE);
tabIndicator.setVisibility(View.INVISIBLE);
btnGetStarted.setAnimation(btnAnim);
visible = true;
}
}