动态设置父活动

时间:2013-10-04 14:44:54

标签: android

所以目前我有一个可以从两个不同活动中获得的活动,问题是我只能将一个活动设置为清单XML文件中的父活动。显然这是糟糕的UX / UI设计,因为活动可能会将用户发回到之前的错误活动,因此我正在尝试动态设置哪个活动是父活动。

麻烦的是我不太确定如何处理这个问题,无论是代码还是XML,所以任何指针都会受到赞赏。 :)

8 个答案:

答案 0 :(得分:55)

对于未来的读者,这里是一个如何根据developer guides实际实施官方/适当解决方案的示例(滚动到以开头的段落“这适用于父活动可能是不同... 的)。

请注意,此解决方案假设您使用Support Library来实现ActionBar,并且至少可以在清单XML文件中设置'默认'父活动,以便在活动时使用正在退出处于不属于您的应用程序的“任务”中(请阅读链接的文档以进行说明)。

// Override BOTH getSupportParentActivityIntent() AND getParentActivityIntent() because
// if your device is running on API 11+ it will call the native
// getParentActivityIntent() method instead of the support version.
// The docs do **NOT** make this part clear and it is important!

@Override
public Intent getSupportParentActivityIntent() {
    return getParentActivityIntentImpl();
}

@Override
public Intent getParentActivityIntent() {
    return getParentActivityIntentImpl();
}

private Intent getParentActivityIntentImpl() {
    Intent i = null;

    // Here you need to do some logic to determine from which Activity you came.
    // example: you could pass a variable through your Intent extras and check that.
    if (parentIsActivityA) {
        i = new Intent(this, ActivityA.class);
        // set any flags or extras that you need.
        // If you are reusing the previous Activity (i.e. bringing it to the top
        // without re-creating a new instance) set these flags:
        i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        // if you are re-using the parent Activity you may not need to set any extras
        i.putExtra("someExtra", "whateverYouNeed");
    } else {
        i = new Intent(this, ActivityB.class);
        // same comments as above
        i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        i.putExtra("someExtra", "whateverYouNeed");
    }

    return i;
}

注意:如果您没有在清单XML文件中设置默认的父Activity,那么您还需要实现onCreateSupportNavigateUpTaskStack(),因为系统将不知道如何为您的任务生成一个Backstack。我没有提供这个部分的任何例子。

我对finish()类型解决方案的想法

在我搜索此问题的解决方案时,我遇到了一些答案,主张覆盖onOptionsItemSelected()并拦截android.R.id.home按钮的策略,以便他们可以简单finish()当前{ {1}}返回上一个屏幕。

在许多情况下,这将达到预期的行为,但我只想指出,这绝对是与正确的UP导航相同。如果您通过其中一个父活动导航到子Activity,则是Activity将返回到正确的上一个屏幕,但是如果您通过通知输入子Activity,该怎么办?在这种情况下finish()按下UP按钮会使您回到主屏幕或您在查看通知之前查看的任何应用程序,而是应该将您发送到应用程序中的正确父活动

答案 1 :(得分:27)

就像这样,您可以动态导航到您的父活动:

getActionBar().setDisplayHomeAsUpEnabled(true);

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    // Respond to the action bar's Up/Home button
    case android.R.id.home:
        finish();
        return true;
    }
    return super.onOptionsItemSelected(item);
}

注意:它会将您重定向到您来自的活动或片段,无论它是否是父母。单击操作栏上/主页按钮将完成当前活动。

答案 2 :(得分:8)

这里有两个概念'Up'和'Back'。 “回来”是显而易见的:在我来到这里之前带我去我所在的地方。通常你不需要关心'后退',因为系统会处理它很好。 “向上”并不那么明显 - 它类似于缩小 - 从元素到集合,从细节到更宽广的画面。

哪些适合您的使用案例?


根据下面的评论:向上按钮从Android清单中提取目的地,但它可以是customized programmatically

答案 3 :(得分:4)

要了解如何正确使用向上导航,请参阅this Android Dev Guide.

请注意,上面的Android开发指南存在一个很大的缺陷,因为NavUtils函数对ICS(及更低版本)和JellyBean(及更高版本)的工作方式不同。 NavUtils中的这个缺陷得到了很好的解释here.

答案 4 :(得分:4)

要覆盖的方法是getParentActivityIntent。

这是我的代码并且完美无缺。

@Override
public Intent getParentActivityIntent() {
    Intent parentIntent= getIntent();
    String className = parentIntent.getStringExtra("ParentClassSource"); 

    Intent newIntent=null;
    try {
        //you need to define the class with package name
        newIntent = new Intent(OnMap.this, Class.forName(className));

    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    return newIntent;
}

来自父活动;

Intent i = new Intent(DataDetailsItem.this, OnMap.class);
i.putExtra("ParentClassSource", "com.package.example.YourParentActivity");
startActivity(i);

答案 5 :(得分:4)

通常,如果“详细”类型的活动具有嵌套/相关内容,则必须提供“向上”导航。 “后退”导航由系统处理,因此您真的不必担心它。

现在为支持“向上”导航付出了额外的努力,有几种方法可以实现:

  1. 具有AndroidManifest中定义的父活动的活动。

    Your Detail Activity
    --------------------
    
    protected void replaceFragment(Bundle fragmentArguments, boolean addToBackStack) {
    
        DetailFragment fragment = new DetailFragment();
        fragment.setArguments(fragmentArguments);
    
        // get your fragment manager, native/support
        FragmentTransaction tr = fragmentManager.beginTransaction();
        tr.replace(containerResId, fragment);
        if (addToBackStack) {
            tr.addToBackStack(null);
        }
        tr.commit();
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    
        switch (item.getItemId()) {
            case android.R.id.home:
                finish();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }
    

    如果只有一个父活动意味着(DetailActivity)总是从(MainActivity)启动,那么这种方法很有效。否则,如果(DetailActivity)从不同的地方启动,则此解决方案将无效。 更多信息:http://developer.android.com/training/implementing-navigation/ancestral.html

  2. (更简单和推荐)具有Fragment和Fragment back-stack的活动:

    object.geometry.computeBoundingBox();
    
    var boundingBox = object.geometry.boundingBox;
    
    position = new THREE.Vector3();
    position.subVectors( boundingBox.max, boundingBox.min );
    position.multiplyScalar( 0.5 );
    position.add( boundingBox.min );
    position.applyMatrix4( object.matrixWorld );
    
    object.geometry.applyMatrix( 
      new THREE.Matrix4()
        .makeTranslation( 
          -(position.x), 
          -(position.y), 
          -(position.z) 
        ) 
    );
    
    object.geometry.verticesNeedUpdate = true;
    
    object.position.x = position.x;
    object.position.y = position.y;
    object.position.z = position.z;
    

    在此解决方案中,如果用户按下“back”,则片段将从片段backstack中弹出,并且用户将被恢复到之前的片段,同时仍保持相同的活动。如果用户按下“向上”,则活动解除并且用户返回到先前的活动(作为父活动)。这里的关键是使用Fragment作为UI,活动作为片段的主机。

  3. 希望这有帮助。

答案 6 :(得分:0)

您可以覆盖“向上”按钮以使其类似于“后退”按钮,如下所示:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            onBackPressed();
    }
    return super.onOptionsItemSelected(item);
}

答案 7 :(得分:0)

科特琳2020

我的活动从不同的活动启动,因此AndroidManifest仅适用于1个父活动。

您可以像这样返回上一个活动:


supportActionBar?.setDisplayHomeAsUpEnabled(true)

override fun onOptionsItemSelected(item: MenuItem?): Boolean {
        when(item!!.itemId){
            android.R.id.home -> {
                finish()
                return true
            }
        }
        return super.onOptionsItemSelected(item)
    }