Не удалось запустить SplashScreen и экран загрузки вместе

#java #android #splash-screen

#java #Android #экран-заставка #ява

Вопрос:

Когда я запускаю свое приложение, я не вижу никакой заставки.Я сделал это из видео, и я установил настройки своего AndroidManifest точно так же, как на видео. Я разместил свой SplashScreen поверх MainActivity в файле манифеста и установил его в обычное состояние (точно так же, как при создании моей заставки), но он все еще не работает.

Мой 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 (Коды на экране ввода):

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



    }
}
  

Комментарии:

1. Привет, попробуйте удалить эти строки, если (restorePrefData()) { Намерение MainActivity = новое намерение(getApplicationContext(),MainActivity.class ); startActivity (MainActivity); finish(); } Я думаю, что это может быть проблемой, из-за которой ваш просмотр не виден

2. если я сделаю это, я должен удалить всю нижнюю часть функций в строках, которые вы сказали.

3. я запускаю свое приложение на своем реальном телефоне, а не на виртуальной машине. я только что понял, что есть 2 одинаковых приложения. почему это произошло?

Ответ №1:

Я новичок в Android, и мое решение может быть не таким, как обычно, вы считаете правильным решением. Сначала извините за мой плохой английский. На мой взгляд, заставка — это единственный и элегантный способ представить вас и ваше приложение. Это должно быть быстро и на короткое время. Я нашел много решений в Интернете, но все страницы и все фрагменты на 90% одинаковы (кажется, что многие люди вырезали / вставляли одно и то же первое решение). Поэтому я решил реализовать свое собственное решение. Извините за мой необработанный код. Я реализовал все в одном действии: и в вашем приложении вы должны вставить только эти изменения:

-) Шаг первый: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, оно должно быть фоном заставки, и в моем примере я подготовил также прямоугольное пространство, куда вставляю свои динамические строки (например, «нажмите для запуска» и «Версия n. 000.00.00»). Мой идентификатор растрового изображения «@drawable / applogothumb», такой же в файле string, я вставил строку «@string /toccasplash». На растровом изображении я также взял пиксельную координату прямоугольного пространства для строк.

-) Шаг третий: объявление и использование в основном приложении:

 @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. Больше мне ничего не требовалось. В то время как отображается экран-заставка, приложение может завершить сборку кода и продолжить выполнение.
Все находится в классе, управление по щелчку для его закрытия и таймер для отсчета времени.
Класс здесь. Прежде чем вы увидите класс, помните, что это мой первый эксперимент, и код внутри сделан для моей собственной области, но я думаю, что есть материал для работы над ним или, может быть, кто-то может подсказать мне, как улучшить эту идею…

 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 amp;amp; 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 amp;amp; figlio != null) 
                padre.removeView(figlio);
            if (mSplash != null) mSplash.recycle();
        }
    };
    // // // // // // // // // // // // // // // // // // // // 
    // // // // // // // // // // // // // // // // // // // //
    // // // // // // // // // // // // // // // // // // // // 
}
  

Вот и все. Любые предложения или улучшения приветствуются.

это результат

Ответ №2:

SplashScreen должно быть, это ваша активность запуска. У вас есть IntroActivity в качестве вашего действия запуска. Обновил свой 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>