それを理解したので、ViewPagerを継承し、非常に簡単に動作する独自のScreenPagerクラスを作成することにしました。 また、xmlと純粋なコードの両方で機能します。
使用する
開始するには、簡単なアプリケーションを作成します。 MainActivityクラスをcom.example.testappに配置し、onCreateメソッドを用意します。 次に、同じディレクトリにScreenPagerクラスを作成し、以下のコードを追加します(現時点では詳しく調べません)。 ScreenPager.java
package com.example.testapp; import android.content.Context; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import java.util.ArrayList; import java.util.List; public class ScreenPager extends ViewPager { private PagerAdapter adapter = new ScreenPagerAdapter(); private List<View> viewList = new ArrayList<View>(); public ScreenPager(Context context) { super(context); init(); } public ScreenPager(Context context, AttributeSet attrs) { super(context, attrs); init(); } @Override public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { return new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); } private void init() { setAdapter(adapter); } @Override public void addView(View child, ViewGroup.LayoutParams params) { addScreen(child); } public void addScreen(View screen) { viewList.add(screen); adapter.notifyDataSetChanged(); } private class ScreenPagerAdapter extends PagerAdapter { @Override public int getCount() { return viewList.size(); } @Override public boolean isViewFromObject(View view, Object o) { return view.equals(o); } @Override public Object instantiateItem(ViewGroup container, int position) { View view = viewList.get(position); container.addView(view); return view; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } } /** * Use - in MainActivity.onCreate add: * LayoutInflater.from(this).setFactory(ScreenPager.getShortNameFactory()); * * @return */ static LayoutInflater.Factory getShortNameFactory() { return new LayoutInflater.Factory() { @Override public View onCreateView(String name, Context context, AttributeSet attrs) { if (ScreenPager.class.getSimpleName().equals(name)) { return new ScreenPager(context, attrs); } return null; } }; } }
これで、res /レイアウトにscreenpager.xmlファイルを作成し、次のコードをそこに配置できます
<?xml version="1.0" encoding="utf-8"?> <com.example.testapp.ScreenPager xmlns:a="http://schemas.android.com/apk/res/android" a:layout_width="match_parent" a:layout_height="match_parent"> <Button a:text=" № 1" /> <Button a:text=" № 2" /> <Button a:text=" № 3" /> <Button a:text=" № 4" /> </com.example.testapp.ScreenPager>
ファイルを手動で作成する場合は、UTF-8エンコーディングで保存することを忘れないでください。 また、文字列は直接挿入するのではなく、文字列リソースに保存する必要があることを忘れないでください。 この記事では、コードを単純化するために意図的にこれを行いませんでした。
MainActivity.onCreateに1行追加します
setContentView(R.layout.screenpager);
それだけです! スライダーは機能しています。 ただし、com.example.testappという長い名前はいです。 しかし、私たちはすべてを可能な限りシンプルにしたいと思いますか?
システムでは、android.viewまたはandroid.widgetのクラスにのみ短い名前を使用できることが判明しました。 クラスでこれを行うには、LayoutInflaterのファクトリを再定義する必要があります。 getShortNameFactoryメソッドを作成しました。このメソッドは、クラスに短い名前を使用できるようにする特別なファクトリーを返します。 onCreateメソッドで設定し、setContentViewの前にこれを行う必要があります。
LayoutInflater.from(this).setFactory(ScreenPager.getShortNameFactory());
IDEがこれを行わない場合は、LayoutInflaterもインポートします。
import android.view.LayoutInflater;
これで、クラスの短縮名を使用できます。
<ScreenPager xmlns:a="http://schemas.android.com/apk/res/android" a:layout_width="match_parent" a:layout_height="match_parent"> <Button a:text=" № 1" /> <Button a:text=" № 2" /> <Button a:text=" № 3" /> <Button a:text=" № 4" /> </ScreenPager>
しかし、それだけではありません! コードで画面を構築できますが、これも簡単です。
ScreenPager screenPager = new ScreenPager(this); Button button1 = new Button(this); button1.setText(" №1"); screenPager.addScreen(button1); Button button2 = new Button(this); button2.setText(" №2"); screenPager.addScreen(button2); //... setContentView(screenPager);
健康に使用してください。 ボタンの代わりに、レイアウトマネージャーまたは他のis-aビューオブジェクトを埋め込むことができます。 確かに、開発環境(私の場合はAndroid Studio)は、layout_widthとlayout_heightの欠如を誓うかもしれませんが、この警告は簡単にオフにすることができます。
例の完全なソースコードを投稿します。
詳細
この記事では、 ViewPagerとPagerAdapterの仕組みを読むことができます。 実際、私はそれを使ってそれらを研究しました。ScreenPagerクラスはViewPagerを継承し、PagerAdapterを継承する非静的ネストクラスScreenPagerAdapterを含みます。 取得する必要がある場合-これはgetAdapter()で実行できます。 また、ScreenPager内には、Viewのリストがあり、これと連動するはずです。
xmlコードが処理されると、ScreenPagerタグ内の各オブジェクトに対してaddViewが呼び出されます。 この関数を再定義し、ViewをaddScreenにリダイレクトしてコレクションに追加し、アダプターに通知します。 したがって、両方の場合-およびコードとxmlを介したスライダーの作成-addScreenを通過します。
次に、LayoutInflater.Factoryを返す小さな静的関数を追加しました。 クラスの短縮名(タグ名と一致する程度)を確認し、成功した場合はオブジェクトを返します。
そして今、楽しい部分です。 たとえば、LinearLayoutがすべての子オブジェクトのlayout_widthとlayout_heightを強制することにお気づきでしょう。 GridLayoutはこれを必要としません。 ウィジェットのユーザーをこのような冗長なコードから解放したかったのですが、この場合も意味がありません。 カスタムコンテナコンポーネントの作成について多くを読む必要がありました。 しかし、そこには必要な情報はありませんでした。 そして、GridLayoutソースの研究だけがこの質問への答えを与えました。 generateLayoutParamsをオーバーライドしてViewGroup.LayoutParams(LayoutParams.MATCH_PARENT、LayoutParams.MATCH_PARENT)を返すだけで十分であることがわかりました。 そしてそれだけです-現在、すべての子ウィジェットは、高さと幅の属性なしで指定できます。
最後に、私が遭遇した1つの興味深い機能について説明します。 LayoutInflater.from(this).setFactoryなしでScreenPagerの使用を減らすことができます。 論理的に考えましょう。 Androidは、android.viewパッケージで短縮名を探しています。 実際、comフォルダーとともにsrcフォルダーにandroidフォルダーを作成することを妨げるものはありません。 また、ファイル自体の中にパッケージの名前を変更することを忘れずに、すでにビューフォルダがあり、そこにScreenPager.javaファイルを配置します。 そして、それはコンパイルして実行します! 試してみてください。 ただし、クラスを他の人のパッケージに入れることは、あまり良いアプローチではありません。 むしろ、興味深い点です。