无法 运行 SplashScreen 和 OnBoarding 屏幕在一起

Couldn't run SplashScreen and OnBoarding screen together

当我 运行 我的应用程序时,我看不到任何 Splash Screen.I 从视频中执行此操作,并且我已将我的 AndroidManifest 设置设置为视频中的设置。我将我的 SplashScreen 放在 Manifest 文件中 MainActivity 的顶部并将其设置为正常(就像我创建我的启动画面时一样activity)但它仍然不起作用。

我的AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.labawsrh.aws.introscreen">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".SplashScreen"></activity>
        <activity android:name=".finalActivity" />
        <activity android:name=".interests" />
        <activity android:name=".IntroActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".MainActivity" />
    </application>

</manifest>

SplashScreen.java:

public class SplashScreen extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash_screen);

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                Intent i = new Intent(SplashScreen.this, MainActivity.class);
                startActivity(i);
                finish();
            }
        }, 3000);

    }
}

activity_splash_screen.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/splash_gradient"
    >

    <ImageView
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:id="@+id/logo"
        android:layout_centerInParent="true"
        android:src="@drawable/whitegift"/>

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="12dp"
        android:textColor="#ffffff"
        android:layout_alignParentBottom="true"
        android:text="Gift Finder"
        android:textSize="60dp"
        android:fontFamily="@font/intoscript"
        android:gravity="center_horizontal"
        android:paddingBottom="130dp"/>

</RelativeLayout>

IntroActivty.java(OnBoarding 屏幕代码):

public class IntroActivity extends AppCompatActivity {

    private ViewPager screenPager;
    IntroViewPagerAdapter introViewPagerAdapter ;
    TabLayout tabIndicator;
    Button btnNext;
    int position = 0 ;
    Button btnGetStarted;
    Animation btnAnim ;
    TextView tvSkip;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // make the activity on full screen

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);


        // when this activity is about to be launch we need to check if its openened before or not

        if (restorePrefData()) {

            Intent mainActivity = new Intent(getApplicationContext(),MainActivity.class );
            startActivity(mainActivity);
            finish();


        }

        setContentView(R.layout.activity_intro);

        // 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.button_animation);
        tvSkip = findViewById(R.id.tv_skip);

        // fill list screen

        final List<ScreenItem> mList = new ArrayList<>();
        mList.add(new ScreenItem("Best Advice!","GiftFinder is an app that gives you the best gift advices.",R.drawable.advice));
        mList.add(new ScreenItem("How It Works?","Our AI code just needs couple info to find the best gift.",R.drawable.aicode));
        mList.add(new ScreenItem("Then..","Let the AI find the best gift for you!",R.drawable.ai));

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

                    // TODO : show the GETSTARTED Button and hide the indicator and the next button

                    loaddLastScreen();


                }



            }
        });

        // tablayout add change listener


        tabIndicator.addOnTabSelectedListener(new TabLayout.BaseOnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {

                if (tab.getPosition() == mList.size()-1) {

                    loaddLastScreen();

                }


            }

            @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) {


                //open main activity

                Intent mainActivity = new Intent(getApplicationContext(), MainActivity.class);
                startActivity(mainActivity);
                // also we need to save a boolean value to storage so next time when the user run the app
                // we could know that he is already checked the intro screen activity
                // i'm going to use shared preferences to that process
                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("myPrefs",MODE_PRIVATE);
        SharedPreferences.Editor editor = pref.edit();
        editor.putBoolean("isIntroOpnend",true);
        editor.commit();


    }

    // show the GETSTARTED 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);
        // TODO : ADD an animation the getstarted button
        // setup animation
        btnGetStarted.setAnimation(btnAnim);



    }
}

SplashScreen 必须是您的启动器 activity。您的启动器 IntroActivity activity。更新了您的 AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.labawsrh.aws.introscreen">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"/>
        <activity android:name=".finalActivity" />
        <activity android:name=".interests" />

          // Made SplashScreen Launcher Activity
        <activity android:name=".SplashScreen">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>


        <activity android:name=".IntroActivity" />
    </application>

</manifest>

我是 android 的新手,我的解决方案可能不像您通常认为的那样是正确的解决方案。首先抱歉我的英语不好。在我看来,启动画面是介绍您和您的应用程序的唯一且优雅的方式。它必须快速且持续时间短。我在互联网上找到了很多解决方案,但所有页面和所有片段的 90% 都是相同的(似乎很多人都在同一个第一个解决方案上进行了剪切/粘贴)。所以我决定实施我自己的解决方案。对不起我的原始代码。我已经实现了所有功能 Activity:在您的应用中,您只需插入以下修改:

-) 第一步:activity_main.xml(主布局),全部包含在一个FrameLayout中:

<androidx.drawerlayout.widget.DrawerLayout 
    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:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:visibility="invisible"
    tools:openDrawer="start">
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:id = "@+id/frameContainer">


        <include
            layout="@layout/app_bar_main"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </FrameLayout>

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>

目标 FrameLayout (@id/frameContainer) 是闪屏容器。

-) 第二步:在drawable目录下插入一张位图,应该是启动画面背景,在我的例子中我还准备了一个矩形space,插入我的动态字符串(例如“touch开始”和“版本号 000.00.00”)。我的位图id是“@drawable/applogothumb”,同样在字符串文件中,我插入了一个字符串“@string/toccasplash”。在位图上,我还为字符串取了矩形 space 的像素坐标。

-) 第三步:在主应用中声明和使用:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Util.hideStatusBar(this);
    setContentView(R.layout.activity_main);
    //Qui lancio la thumb, il controllo passato [ frameContainer ] deve essere
    //un FrameLayout in modo che la thumb stia sopra tutto il resto
    CMainSplashBox thumb = new CMainSplashBox(this,
            R.id.frameContainer,                //FrameLayout ID Step 1
            R.drawable.applogothumb,            //Bitmap ID Step 2
            R.string.toccasplash,               //Stringa ID
            CVersions.APP_VERSION,              //Version number (String)
            //pixel coordinate of the rectangular space for the strings
            new Rect(TWRITE_ORG_X,TWRITE_ORG_Y,TWRITE_END_X,TWRITE_END_Y),
            //Time duration in seconds
            10);                         
    mCsd = new CSerializeData(this);
    mCsd.loadConfiguration();
    ....
    ....

如您所见,所有内容都在 CMainSplashBox class 中进行管理。我不需要其他任何东西。同时显示启动画面,应用程序可以完成构建代码并继续执行。 一切都在 class 中,管理点击关闭它和计时器计时。 class 在这里。在你看到 class 之前,请记住这是我的第一个实验,里面的代码是为我自己的范围编写的,但我认为它有工作的材料,或者有人可以建议我如何改进这个想法...

public class CMainSplashBox extends LinearLayoutCompat {
    private Timer statusCommandsTimer = null;
    private int mDurata = 5000; //seconds/1000
    private int mPeriodo = 1000;
    private FrameLayout padre;
    private CMainSplashBox figlio;
    private Context mCtx;
    private Bitmap mSplash;
    private int mIdSplash = -1;
    private String mText;
    private String mVer;
    private float DIM_X = 963;
    private float DIM_Y = 700;
    private float ORG_X = 95;
    private float ORG_Y = 475;
    private float END_X = 877;
    private float END_Y = 568;
    private int mFontMis = 70;
    private double mTotTxSpace = 50;
    private double mLfontD = 15;
    private double mBfontD = 28;

    /*
    @context = appContext
    @id = FrameLayout ID
    @idd = Bitmap ID
    @idText = String ID
    @ver = Version number string
    @th = Pixel coordinate
    @durata = wait in second
     */
    public CMainSplashBox(Context context,int id,int idd,int idText ,String ver, Rect 
                                    th,int durata){
        super(context);
        mCtx = context;
        mDurata = durata * 1000;
        mIdSplash = idd;
        ORG_X = th.left;
        ORG_Y = th.top;
        END_X = th.right;
        END_Y = th.bottom;
        mVer = "Version.: "+ver;
        mText = ((AppCompatActivity)context).getText(idText).toString();
        Point pt = Util.getOriginalBitmapDims(context.getResources(),idd);
        DIM_X = pt.x;
        DIM_Y = pt.y;
        FrameLayout.LayoutParams vgl = new 
                          FrameLayout.LayoutParams(MATCH_PARENT,MATCH_PARENT);
        vgl.gravity= Gravity.CENTER;
        figlio = this;
        padre = ((AppCompatActivity)context).findViewById(id);
        padre.addView(this);
        setBackgroundColor(0xCC000000);
        setLayoutParams(vgl);
        setPadding(5,5,5,5);
        setEnabled(true);
        statusCommandsTimer = startTimer(statusCommandsTimer,0, mPeriodo);
        setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //here I can close the Splash if the screen have been touched
                mDurata = 0;
            }
        });
    }

    //Draw the splash screen and make some calculations on the bitmaps
    //Util is my library with some common routines
    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mSplash == null){
            mSplash = Util.getBitmap(mCtx,mIdSplash,canvas.getWidth(),canvas.getHeight());
        }
        if (mSplash != null){
            int dmx = mSplash.getWidth();
            int dmy = mSplash.getHeight();
            float dx = (canvas.getWidth()-dmx)/2;
            float dy = (canvas.getHeight()-dmy)/2;
            canvas.drawBitmap(mSplash,dx,dy,null);
            int orgx = (int)(((ORG_X * dmx)/DIM_X)+dx);
            int orgy = (int)(((ORG_Y * dmy)/DIM_Y)+dy);
            int endx = (int)(((END_X * dmx)/DIM_X)+dx);
            int endy = (int)(((END_Y * dmy)/DIM_Y)+dy);
            Paint p = new Paint();
            Rect bounds = new Rect();
            p.setTextSize(mFontMis);
            p.getTextBounds(mText, 0, mText.length(), bounds);
            p.setTypeface(Typeface.DEFAULT_BOLD);
            int thumbw = (endx-orgx)-10;
            bounds.offset(0, -bounds.top);
            double spt = (bounds.height() * mTotTxSpace)/mBfontD;
            if ((endy-orgy) < (int)spt){
                mFontMis =(int)(((endy-orgy) * mFontMis) / spt);
                p.setTextSize(mFontMis);
                p.getTextBounds(mText, 0, mText.length(), bounds);
                bounds.offset(0, -bounds.top);
                spt = (bounds.height() * mTotTxSpace)/mBfontD;
                }
            if (thumbw < bounds.width()){
                mFontMis = (thumbw*mFontMis)/bounds.width();
                p.setTextSize(mFontMis);
                p.getTextBounds(mText, 0, mText.length(), bounds);
                bounds.offset(0, -bounds.top);
                }
            dmx = ((endx-orgx)-bounds.width())/2;
            dmy = (endy-orgy)-bounds.height();
            spt = bounds.height();
            p.setColor(0xff000000);                                        
            canvas.drawText(mText, orgx+dmx, endy-dmy, p);          
            int fm = (int)((mFontMis * mLfontD) / mBfontD);
            p.setTextSize(fm);
            p.getTextBounds(mText, 0, mVer.length(), bounds);
            bounds.offset(0, -bounds.top);
            dmx = ((endx-orgx)-bounds.width())/2;
            int spy = (int)(mTotTxSpace -(mLfontD+mBfontD));
            dmy = (int)((endy-orgy)-(bounds.height()+(((endy-orgy) * 
            spy)/mTotTxSpace)));
            canvas.drawText(mVer, orgx+dmx, (endy-dmy)+(float)spt, p);          
        }
    }


    @Override
    public void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (mSplash != null) mSplash.recycle();
        mSplash = null;
        //Ridisegna
        invalidate();
    }

    // // // // // // // // // // // // // // // // // // // // // // 
    // // // // // // // // // // // // // // // // // // // // // //
    // // // // // // // // // // // // // // // // // // // // // //    
    // Wait Timer

    private Timer startTimer(Timer tt, int delay, int period) {
        Timer itt = tt;
        if (itt == null) {
            itt = new Timer();
            itt.schedule(new TimerTask() {
                @Override
                public void run() {
                    TimeCounter();
                }
            }, delay, period);
        }
        return itt;
    }


    private void stopTimers(Timer tt) {
        if (tt != null) {
            tt.cancel();
            tt.purge();
        }
    }
    
    //Calculate the residual time
    private void TimeCounter(){
        mDurata -= mPeriodo;
        if (mDurata <= 0 && mCtx instanceof AppCompatActivity){
            stopTimers(statusCommandsTimer);
            ((AppCompatActivity)mCtx).runOnUiThread(Timer_Tick);
        }
    }

    //This function is necessary because I have to remove the splash screen and 
    //Remove the bitmap from the timer thread
    private Runnable Timer_Tick = new Runnable() {
        public void run() {
            setEnabled(false);
            setVisibility(INVISIBLE);
            //for safety only  as you are doing onClick
            if(null!=padre && figlio != null) 
                padre.removeView(figlio);
            if (mSplash != null) mSplash.recycle();
        }
    };
    // // // // // // // // // // // // // // // // // // // // 
    // // // // // // // // // // // // // // // // // // // //
    // // // // // // // // // // // // // // // // // // // // 
}

就是这样。欢迎任何建议或改进。