android 是否可以通过扩展ConstraintLayout并加载到特定的XML中来创建“可单击项”,以便稍后应用多态性?

wydwbb8l  于 2022-12-09  发布在  Android
关注(0)|答案(1)|浏览(81)

我在考虑从文件中膨胀XML对象,它基本上是一个ConstraintLayout,里面有一些TextView。但是通过像这样扩展ConstraintLayout,并使用以下内容代替ConstraintLayout:

public class CommonLayout extends ConstraintLayout {
    private TextView myTitle;
    private TextView myDesc;

    public CommonLayout(@NonNull Context context) {
        super(context);
        loadWidgets();
    }

    public CommonLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        loadWidgets();
    }

    public CommonLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        loadWidgets();
    }

    public CommonLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        loadWidgets();
    }

    private void loadWidgets() {
        myTitle = this.findViewById(R.id.layoutTitle);
        myDesc = this.findViewById(R.id.layoutDesc);
    }

    // ----
    public void setMyTitle(String input) {
        myTitle.setText(input);
    }

    public void setMyDescription(String input) {
        myDesc.setText(input);
    }
}

我想扩展ConstraintLayout可能看起来很奇怪,我知道......重要的是我可以膨胀这些ConstraintLayout子级(基本上是ConstraintLayout的克隆,它使用一些方法在XML“CommonLayout”文件中查找默认TextViews并设置其文本--换句话说,将子视图逻辑隔离并封装在CommonLayout本身中)。如果它能工作,那么我将使用更多ConstraintLayout子级和一个通用接口来应用polimorfism。

**要点是将膨胀的“CommonLayout“加载到某个LinearLayout中。这些“CommonLayout”将包含我想动态设置的TextView,这些CommonLayout对象将总是从view_commonlayout.xml文件膨胀。**如果这样做有效,我想用不同的ConstraintLayout子级来升级它。“但是为什么要扩展ConstraintLayout呢?可以吗?"难道您不应该为此而膨胀普通的ConstraintLayout吗?”嗯......也许......但如果我出于某种原因需要为所有子对象提供一个公共接口,我可以通过扩展ConstraintLayout,在情况需要时立即添加implements I_SomeCommonInterface以应用polimorfism......或者至少是这样的想法

......然后,我想或多或少地这样使用它:

// ...from some fragment...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.the_fragment, container, false);

    // XXX The point is inflating CommonLayouts into this LinearLayout
    LinearLayout mainLayout = view.findViewById(R.id.theLinearLayout);

    //CommonLayout obj1 = new CommonLayout(getContext());
    CommonLayout obj1 = (CommonLayout) LayoutInflater.from(view.getContext()).inflate(R.layout.view_commonlayout, mainLayout, false);

    obj1.setMyTitle("Good morning");
    obj1.setMyDescription(getString(R.string.lorem_ipsum));

    mainLayout.addView(obj1);

    return view;
}

我想从这个XML view_commonlayout.xml文件加载每个CommonLayout:

<com.mydomain.myapp.views.custom_widgets.CommonLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="10dp"
android:layout_marginHorizontal="10dp"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">

<TextView
    android:id="@+id/layoutTitle"
    android:textColor="#FFFFFF"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Here goes THE TITLE"
    tools:layout_editor_absoluteX="15dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    android:textSize="24sp"/>
<TextView
    android:id="@+id/layoutDesc"
    android:textColor="#FFFFFF"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Here goes the description"
    tools:layout_editor_absoluteX="15dp"
    app:layout_constraintTop_toBottomOf="@id/layoutTitle"
    app:layout_constraintStart_toStartOf="parent"
    android:textSize="12sp"/>

</com.mydomain.myapp.views.custom_widgets.CommonLayout>

我做错了什么来实现我在这里尝试的?当使用setMyTitlesetMyDescription时,NullPointerException总是会失败(我现在开始做整个事情的第一个“多米诺堆栈测试”,在解决NullpointerException后,其他一些事情可能会失败,但现在这是我首先关心的问题...)
至少,我知道,(通过TraceBack)myTitle变量是空的。所以,this.findViewById()失败了。可能是因为我不知道如何从XML文件膨胀并将其全部保存在同一个类中(显然,我的LayoutInflater.inflate(params)尝试仍然使它以与使用new操作符相同的方式失败)。我被困在那里了...

澄清:

计划的视图结构并不打算加载任何类型的数据,既不从数据库也不从任何用户首选项或任何东西。目的是使一个“动态主菜单”与此。
现在,如果它能用,我会用几个静态选项填充它。但是,在将来,我可能会根据用户使用应用的历史来使它变得有点动态。但是现在,我很高兴如果我能用计划的结构或类似的结构来完成这件事。
我的想法还是有可能会失效。我希望,如果我膨胀一些XML文件(如view_commonlayout.xml)我可以将它赋给XML文件的顶级父变量类型(在本例中为CommonLayout),并从那里访问(文本视图)。也许,只是也许,在CommonLayout类本身中封装此XML结构的行为以及与之相关的所有内容。(即使我不确定所有的实现细节)。这些疯狂的想法中的一些可能是不可行的,如果是这样的话,我将不得不寻找一些解决方案。也许我应该尝试不同的方法,比如创建一个新的“ Package 类”而不是扩展ConstraintLayout?
目的
这一切都是为了给我已经发布在Google Play商店的应用增加一个新功能,类似于“动态登陆菜单”,以吸引用户对我的应用的一些最重要功能的注意。我想分享这个链接,但它只在我的祖国可用,我不确定这是否有助于澄清这个问题。
这就像我为每个公共布局创建了几个选项,带有选项标题和选项描述。加载的每个CommonLayout都有其OnClickListener来或多或少地打开某个菜单。现在我只对一种类型的XML结构感到满意(view_commonlayout.xml中的一个),但将来我希望使用类似ConstraintLayout的父级来提供其他XML结构,但是不同的子视图(例如,不是两个TextView,而是一个ImageView和一个TextView;或者可能是一些小型表单来提交一些东西...在这种情况下,我可能需要提取一个公共接口来应用polimorfism(例如,使用方法setOnClickListenersetLayoutTitle或类似的东西来拥有所有公共接口...))。

NullPointerException已解决

最后,解决NullPointerException比我想象的要容易......我不确定这个解决方案是否优雅,但它起作用了。我只需要稍微修改CommonLayout类,去掉loadWidgets方法,并像这样修改setter:

public void setMyTitle(String input) {
    myTitle = this.findViewById(R.id.layoutTitle);
    myTitle.setText(input);
}

public void setMyDescription(String input) {
    myDesc = this.findViewById(R.id.layoutDesc);
    myDesc.setText(input);
}

尽管它解决了导致应用崩溃的问题,但现在自我回答这个问题还为时过早。我仍然需要弄清楚我是否可以将膨胀的CommonLayout变成一个按钮(可能不会那么难)......而且,我想扩展ConstraintLayout的全部意义只是我可以强制孩子实现一个接口(这让我考虑编辑这个问题的标题)

o0lyfsai

o0lyfsai1#

简短的回答是:是的,您可以扩展ConstraintLayout,像普通ConstraintLayout一样使用XML资源文件中的子元素,似乎一切都与您对CostraintLayout的期望一样。
我想从这里得到一个更详细的答案,关于多态性的优点,但是我需要更多的时间。

相关问题