English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Рендеринг стильного вводного интерфейса в Android

Сначала посмотрим на интерфейс, который мы будем разрабатывать (три изображения, на последнем изображении появится кнопка "Начать опыт",小红点也会一起滑动):


Сначала посмотрим на файл разметки:

 <?xml version="1.0" encoding="utf-8"?>
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android">
   xmlns:tools="http://schemas.android.com/tools"
   android:id="@+id/activity_guide"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context="com.coderwei.a71_zhbj.activity.GuideActivity">
   <android.support.v4.view.ViewPager>
     android:id="@+id/vp_guide"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     />
   <Button
     android:layout_centerHorizontal="true"
    android:layout_alignParentBottom="true"
    android:layout_marginBottom="70dp"
    android:padding="10dp"
    android:id="@+id/start_btn"
    android:textColor="#f1eaea"
   android:background="#e71616"
   android:text="开始体验"
   android:visibility="invisible"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content" />
  <RelativeLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:layout_marginBottom="30dp"
   <LinearLayout
     android:id="@+id/ll_container"
     android:layout_width="wrap_content"
    android:layout_height="wrap_content">
   </LinearLayout>
  <ImageView
    android:id="@+id/iv_red"
   android:src="@drawable/shap_red"
   android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
 </RelativeLayout>
 </RelativeLayout>

Затем идет код:

public class GuideActivity extends Activity {
   private ViewPager mViewPager;
   private int[] mImageIds = new int[]{R.drawable.guide_1,R.drawable.guide_2,R.drawable.guide_3};
   private ArrayList<ImageView> mImageViewList;
   private LinearLayout llContainer;
   private ImageView ivRedPoint;
   private int mPaintDis;
   private Button start_btn;
  @Override
 protected void onCreate(Bundle savedInstanceState) {
   uper.onCreate(savedInstanceState);
   requestWindowFeature(Window.FEATURE_NO_TITLE);
   setContentView(R.layout.activity_guide);
   mViewPager = (ViewPager)findViewById(R.id.vp_guide);
   llContainer = (LinearLayout) findViewById(R.id.ll_container);
   ivRedPoint = (ImageView) findViewById(R.id.iv_red);
   start_btn = (Button) findViewById(R.id.start_btn);
   initData();
   GuideAdapter adapter = new GuideAdapter();
   mViewPager.setAdapter(adapter);
   //监听布局是否已经完成 布局的位置是否已经确定
    ivRedPoint.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
      @Override
      public void onGlobalLayout() {
       //避免重复回调  出于兼容性考虑,使用了过时的方法
        ivRedPoint.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        //布局完成了就获取第一个小灰点和第二个之间left的距离
        mPaintDis =  llContainer.getChildAt(1).getLeft()-llContainer.getChildAt(0).getLeft();
        System.out.println("距离:"+mPaintDis);
      }
   });
  //ViewPager滑动Pager监听
  mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
     //滑动过程中的回调
     @Override
     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
     //当滑到第二个Pager的时候,positionOffset百分比会变成0,position会变成1,所以后面要加上position*mPaintDis
     int letfMargin = (int)(mPaintDis * positionOffset) + position * mPaintDis;
     //在父布局控件中设置他的leftMargin边距
      RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)ivRedPoint.getLayoutParams();
     params.leftMargin = letfMargin;
     ivRedPoint.setLayoutParams(params);
     }
     @Override
      public void onPageSelected(int position) {
        System.out.println("position:"+position);
        if (position==mImageViewList.size()-1){
         start_btn.setVisibility(View.VISIBLE);
       }
     }
     @Override
      public void onPageScrollStateChanged(int state) {
       System.out.println("state:"+state);
      }
    });
  }
  private void initData(){
    mImageViewList = new ArrayList<>();
    for (int i=0; i<mImageIds.length; i++){
      //создание ImageView и добавление mImgaeViewIds
      ImageView view = new ImageView(this);
      view.setBackgroundResource(mImageIds[i]);
      //добавление в коллекцию ImageView
      mImageViewList.add(view);
     //маленькая точка  одна маленькая серая точка это ImageView
     ImageView pointView = new ImageView(this);
      pointView.setImageResource(R.drawable.shape);
      //инициализация параметров макета, родительский контроллер кто, инициализируйте параметры макета, кто это
     LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
     if (i>0){
       //когда количество добавленных маленьких圆点的 exceeds один, установите левый отступ текущей маленькой круговой точки в 10dp;
        params.leftMargin=10;
      }
     //установка ширины и высоты маленькой серой точки по содержимому
      pointView.setLayoutParams(params);
      //добавление маленькой серой точки в LinearLayout
      llContainer.addView(pointView);
    }
   }
 class GuideAdapter extends PagerAdapter{
    //количество элементов
    @Override
    public int getCount() {
       возврат mImageViewList.size();
    }
    @Override
     public boolean isViewFromObject(View view, Object object) {
       возврат view == object;
    }
    //инициализация макета элемента
     @Override
     public Object instantiateItem(ViewGroup container, int position) {
       ImageView view = mImageViewList.get(position);
      container.addView(view);
      возврат view;
    }
    //удаление элемента
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
      container.removeView((View)object);
    }
  }
 } 

小灰点:

<?xml version="1.0" encoding="utf-8"?>
<shape
   android:shape="oval"
   xmlns:android="http://schemas.android.com/apk/res/android">
   <!--小灰点-->
   <solid android:color="#cccccc"/>
   <size android:width="10dp" android:height="10dp"/>
</shape>

小红点:

<?xml version="1.0" encoding="utf-8"?>
 <shape
   android:shape="oval"
   xmlns:android="http://schemas.android.com/apk/res/android">
   <solid android:color="#f00"/>
   <size android:width="10dp" android:height="10dp"/>
 </shape>

ViewPage 都很简单,上一个博文也详细介绍了,这里就不细说了,主要是下面的小红点跟着 Pager 一起走。

上面其实是三个小灰点,然后小灰点的上面有一个小红点,通过计算出第一个小灰点与第二个小灰点之间的距离,我们就可以用设置 ViewPager 的滑动监听,然后让小红点跟着 pager 一起动(改变的是父控件中的内边距)。

计算小灰点之间的距离时需要注意的是,必须等到布局位置确定下来的才能得到小灰点之间的距离(界面生成的过程 measure->layout(确定位置)->draw(在 activity 的 onCreate 方法执行结束之后才会走此流程)),所以要设置 layout 的监听:

ivRedPoint.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener())

然后得到小灰点之间的距离:

mPaintDis = llContainer.getChildAt(1).getLeft() - llContainer.getChildAt(0).getLeft();

需要注意的是这句代码:
int letfMargin = (int)(mPaintDis * positionOffset) + position * mPaintDis;

positionOffset is the percentage of the current slide, when entering the second page, the value is 0,}
position represents the current page number, starting from 0, which means when I slide to the second page, mPaintDis*0+1*mPaintDis;

PS: Обзор思路:

  1. Страница состоит из ViewPager + Button + RelativeLayout(LinearLayout + TextView)
  2. LinearLayout содержит точки серого цвета, количество которых зависит от количества ViewPager, поэтому при добавлении точек серого цвета в LinearLayout они добавляются одновременно с добавлением ресурсов изображений ViewPager в набор.
  3. Затем красная точка - это TextView, и из-за относительного макета его начальное положение будет совпадать с первой точкой серого цвета.
  4. Затем слушайте событие скольжения ViewPager, перемещая положение красной точки, вычисляя разницу в отступе между левой стороной первой и второй точки серого цвета к левой стороне LinearLayout, но для определения положения необходимо убедиться, что положение уже определено в макете, поэтому нам нужно слушать, определено ли положение макета, и только затем вычислять разницу в положении.

Вот и все, что есть в этой статье, мы надеемся, что это поможет вам в изучении, и希望大家多多 поддерживать呐喊教程。

Заявление: содержимое статьи взято из Интернета, авторские права принадлежат авторам, контент предоставлен пользователями Интернета, сайт не имеет права собственности, не был отредактирован вручную, и не несет ответственности за соответствующие юридические вопросы. Если вы обнаружите подозрительное содержимое о нарушении авторских прав, пожалуйста, отправьте письмо по адресу: notice#oldtoolbag.com (при отправке письма замените # на @) для сообщения и предоставления соответствующих доказательств. В случае подтверждения мы незамедлительно удалим подозрительное содержимое.

Основной учебник
Рекомендуем к просмотру