إنشاء صفحة onBoarding في الاندرويد ستوديو وحفظ القيمة داخل sharedPreferences

إنشاء صفحة onBoarding في الاندرويد ستوديو وحفظ القيمة داخل sharedPreferences


 إنشاء صفحة 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

يمكنك تحميل الملحقات من هنا | او من هنا


الالوان التي نحتاج اليها في التصميم

قم بإضافة الالوان التاليه في الملف المخصص للالوان لانك سوف تحتاج اليها ويمكنك استبدال الالوان باي الوان اخرى تريد التعامل معها .


colors.xml

    <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>
    


الثيم الذي سوف نعمل عليه

الثيم الذي سوف نعمل عليه سيكون  محتوي على هذه الالوان التي يمكنك استخدامها .


theme.xml

<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


الان سوف نقوم بعمل ملف للانميشن الخاص بالزر وبكل بساطة سوف نقوم بانشاء ملف anim وبعدها وضع الكود التاليه بداخله .

الانميشن الذي سوف نقوم بعمل على زر get started


anim.xml

<?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>

التصميم الذي سوف نقوم بتغييره اثناء عملية التنقل بين الصفحات

الان ناتي الى الlayout الذي يحتوي على الصفحات التي سوف نقوم بتبديلها خلال التغيير بين الصفحات .

layout_screen.xml

<?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 لتغيير الصفحات اثناء عملية التنقل

الان نحتاج الى انشاء adapter  مخصص لل PagerAdapter  لكي يقوم بالتغيير بين الصفحات في نفس المكان .

IntroViewPagerAdapter.java

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);

    }
}


تصميم الصفحة الرئيسيه التي يعمل عليها التصميم

الان ناتي الى التصميم وهو عباره عن ViewPager وهو نفس فكرة الfragment ولكن يعمل في نفس الصفحة ويعرض مجموعة من الصور او النصوص او التصاميم التي تقوم بها 

onBoarding.xml

<?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 للسماح بتغيير البيانات اثناء عمليات التنقل

الان لكي نسمح بتغيير البيانات سوف نقوم بعمل class يحتوي على الmodel , وهو نص وصورة ويمكنك التغيير واضافة عناصر اخرى اذا كنت ترغب .

ScreenItem.java

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;
    }
}

الاكواد المسؤوله عن عملية الانتقال من صفحة  للاخرى وتغيير البيانات 

الان ياتي دور الكود الاخير وهو لعرض الصفحات والكود وحفظ القيمة داخل shared لكي لا تفتح في المرات المقبلة للتطبيق ويتم نقلة الى صفحة اخرى مباشرة .

OnBoarding.java

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;
    }
}

لمزيد من المقالات :

تعليقات