(Android)在一组对象上实现滑动手势

时间:2017-07-05 19:48:28

标签: android android-studio swipe swipe-gesture

*更新 - >滑动手势现在可以工作(类“PieceViewFragment”和“OnSwipeTouchListener”已相应更新),但我真的希望获得从一个项目转换到另一个项目时获得的漂亮视觉效果(移动)。现在它只是切换到下一个或上一个项目。

* NEW UPDATE - >当从一个项目转换到另一个项目时,我能够获得良好的视觉效果(运动)(感谢Nobby_Nobody的最后评论和链接)。

在此处获取代码 - > My Project on github

我需要帮助来通过Android个人项目(库存清单)中的项目集合实施滑动手势。我已经看过很多例子,但我似乎无法正确实现它。

申请很简单。它只是一个库存(InventairesPieces)实现为项目(PieceModel)的滚动列表(InventairesPiecesActivity和InventairesPiecesFragment),单击一个项目后,细节(PieceViewActivity和PieceViewFragment)将在另一个活动中打开。

在详细信息活动(PieceViewActivity和PieceViewFragment)中,我希望能够跨项目轻扫而不是每次都返回滚动列表。

到目前为止,我尝试将“ViewPager”设置为在我的片段(PieceViewFragment)上扩展FragmentStatePagerAdapter的适配器,但它无法正常工作:

*单击某个项目时,无论单击哪个项目,它都会显示列表的第一项。操作栏中的标题也不匹配。 *

这是“PieceViewActivity”类:

public class PieceViewActivity extends AppCompatActivity {

private InventairePieces inventairePieces;

private PieceModel piece;

private int position;

/**
 * The pager widget, which handles animation and allows swiping horizontally to access previous
 * and next wizard steps.
 */
private ViewPager mViewPager;

/**
 * The pager adapter, which provides the pages to the view pager widget.
 */
private InventairePiecesPagerAdapter inventairePiecesPagerAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_piece_view);

    // receives the intent
    Intent intent = this.getIntent();
    inventairePieces = (InventairePieces) intent.getSerializableExtra("inventairePieces");
    position = (int) intent.getSerializableExtra("posClicked");

    // Instantiate a ViewPager and a PagerAdapter.
    inventairePiecesPagerAdapter = new InventairePiecesPagerAdapter(getSupportFragmentManager());
    mViewPager = (ViewPager) findViewById(R.id.activity_piece_view_container);
    mViewPager.setAdapter(inventairePiecesPagerAdapter);
}

public class InventairePiecesPagerAdapter extends FragmentStatePagerAdapter {

    public InventairePiecesPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int posView) {
        return PieceViewFragment.create(posView, position, inventairePieces);
    }

    @Override
    //the amount of items in the inventory
    public int getCount() {
        return inventairePieces.getInventairePieces().size();
    }

}

}

这是“PieceViewFragment”类(详细信息或卡片):

public class PieceViewFragment extends Fragment {

protected OnSwipeTouchListener onSwipeTouchListener;

private InventairePieces inventairePieces;

private PieceModel piece;

private int positionClicked;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    final View rootView = inflater.inflate(R.layout.fragment_piece_view, null, false);

    // receives the intent
    Intent intent = getActivity().getIntent();
    inventairePieces = (InventairePieces) intent.getSerializableExtra("inventairePieces");
    positionClicked = (int) intent.getSerializableExtra("posClicked");
    piece = inventairePieces.getInventairePieces().get(positionClicked);

    // sets the title in the action bar
    getActivity().setTitle(piece.getNomPiece());

    Log.v("Fragment", "Pos Clicked: " + positionClicked);
    Log.v("Fragment" , "Piece: " + piece.getNomPiece());
    Log.v("Fragment", "Inventaire: " + inventairePieces.getInventairePieces().size());

    // the item card
    ((TextView) rootView.findViewById(R.id.codePiece_text)).setText(String.valueOf("# " + piece.getCodePiece()));
    ((TextView) rootView.findViewById(R.id.nomPiece_text)).setText(piece.getNomPiece());
    ((TextView) rootView.findViewById(R.id.descriptionPiece_text)).setText(piece.getDescriptionPiece());
    ((TextView) rootView.findViewById(R.id.dimensionPiece_text)).setText(String.valueOf(piece.getDimensionPiece()) + " mm");
    ((TextView) rootView.findViewById(R.id.prixCoutantPiece_text)).setText(String.valueOf(piece.getPrixCoutantPiece()) + " $");
    ((TextView) rootView.findViewById(R.id.qtyPiece_text)).setText(String.valueOf(piece.getQtyPiece()));
    ((TextView) rootView.findViewById(R.id.typePiece_text)).setText(piece.getTypePiece());
    ((TextView) rootView.findViewById(R.id.categoriePiece_text)).setText(piece.getCategoriePiece());

    rootView.setOnTouchListener(new OnSwipeTouchListener(getContext()){
        @Override
        public void onSwipeRight() {
            super.onSwipeRight();
            Log.v("Fragment", "onSwipeRight - ");
            if (positionClicked > 0) {
                positionClicked--;
                piece = inventairePieces.getInventairePieces().get(positionClicked);

                // sets the title in the action bar
                getActivity().setTitle(piece.getNomPiece());

                // the item card
                ((TextView) rootView.findViewById(R.id.codePiece_text)).setText(String.valueOf("# " + piece.getCodePiece()));
                ((TextView) rootView.findViewById(R.id.nomPiece_text)).setText(piece.getNomPiece());
                ((TextView) rootView.findViewById(R.id.descriptionPiece_text)).setText(piece.getDescriptionPiece());
                ((TextView) rootView.findViewById(R.id.dimensionPiece_text)).setText(String.valueOf(piece.getDimensionPiece()) + " mm");
                ((TextView) rootView.findViewById(R.id.prixCoutantPiece_text)).setText(String.valueOf(piece.getPrixCoutantPiece()) + " $");
                ((TextView) rootView.findViewById(R.id.qtyPiece_text)).setText(String.valueOf(piece.getQtyPiece()));
                ((TextView) rootView.findViewById(R.id.typePiece_text)).setText(piece.getTypePiece());
                ((TextView) rootView.findViewById(R.id.categoriePiece_text)).setText(piece.getCategoriePiece());

                Log.v("Fragment", "Pos Clicked: " + positionClicked);
                Log.v("Fragment" , "Piece: " + piece.getNomPiece());
                Log.v("Fragment", "Inventaire: " + inventairePieces.getInventairePieces().size());
            }
        }
        @Override
        public void onSwipeLeft() {
            super.onSwipeLeft();
            Log.v("Fragment", "onSwipeLeft + ");
            if(positionClicked < inventairePieces.getInventairePieces().size()-1) {
                positionClicked++;
                piece = inventairePieces.getInventairePieces().get(positionClicked);

                // sets the title in the action bar
                getActivity().setTitle(piece.getNomPiece());

                // the item card
                ((TextView) rootView.findViewById(R.id.codePiece_text)).setText(String.valueOf("# " + piece.getCodePiece()));
                ((TextView) rootView.findViewById(R.id.nomPiece_text)).setText(piece.getNomPiece());
                ((TextView) rootView.findViewById(R.id.descriptionPiece_text)).setText(piece.getDescriptionPiece());
                ((TextView) rootView.findViewById(R.id.dimensionPiece_text)).setText(String.valueOf(piece.getDimensionPiece()) + " mm");
                ((TextView) rootView.findViewById(R.id.prixCoutantPiece_text)).setText(String.valueOf(piece.getPrixCoutantPiece()) + " $");
                ((TextView) rootView.findViewById(R.id.qtyPiece_text)).setText(String.valueOf(piece.getQtyPiece()));
                ((TextView) rootView.findViewById(R.id.typePiece_text)).setText(piece.getTypePiece());
                ((TextView) rootView.findViewById(R.id.categoriePiece_text)).setText(piece.getCategoriePiece());

                Log.v("Fragment", "Pos Clicked: " + positionClicked);
                Log.v("Fragment" , "Piece: " + piece.getNomPiece());
                Log.v("Fragment", "Inventaire: " + inventairePieces.getInventairePieces().size());
            }
        }
    });

    return rootView;
}

}

这里是处理手势的新OnSwipeTouchListener类:

public class OnSwipeTouchListener implements View.OnTouchListener {

private GestureDetector gestureDetector;

public OnSwipeTouchListener(Context c) {
    gestureDetector = new GestureDetector(c, new GestureListener());
}

public boolean onTouch(final View view, final MotionEvent motionEvent) {
    return gestureDetector.onTouchEvent(motionEvent);
}

private final class GestureListener extends GestureDetector.SimpleOnGestureListener {

    private static final int SWIPE_THRESHOLD = 100;
    private static final int SWIPE_VELOCITY_THRESHOLD = 100;

    @Override
    public boolean onDown(MotionEvent e) {
        return true;
    }

    // Determines the fling velocity and then fires the appropriate swipe event accordingly
    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        boolean result = false;
        try {
            float diffY = e2.getY() - e1.getY();
            float diffX = e2.getX() - e1.getX();
            if (Math.abs(diffX) > Math.abs(diffY)) {
                if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffX > 0) {
                        onSwipeRight();
                    } else {
                        onSwipeLeft();
                    }
                }
            } else {
                if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffY > 0) {
                        onSwipeDown();
                    } else {
                        onSwipeUp();
                    }
                }
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return result;
    }
}

public void onSwipeRight() {
}

public void onSwipeLeft() {
}

public void onSwipeUp() {
}

public void onSwipeDown() {
}

}

这里是“InventairesPiecesFragment”类,您点击滚动列表中的项目:

public class InventairePiecesFragment extends Fragment{

private ArrayAdapter<PieceModel> inventairePiecesAdapter;

private InventairePieces inventairePieces;

private PieceModel piece;

private Bundle bundle;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    FloatingActionButton fab = (FloatingActionButton) container.findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(getActivity(), PieceEditActivity.class);
            intent.putExtra("piece", piece);
            intent.putExtra("inventairePieces", inventairePieces);
            startActivityForResult(intent, 1);
        }
    });

    inventairePieces = new InventairePieces(new ArrayList<PieceModel>());
    this.readInventairePiece();

    inventairePiecesAdapter = new ArrayAdapter<>(
            getActivity(),
            R.layout.liste_pieces_inventaire,
            R.id.liste_pieces_inventaire_textview,
            inventairePieces.getInventairePieces());

    View rootView = inflater.inflate(R.layout.fragment_pieces_inventaire, container, false);

    ListView inventairePiecesAdapterView = (ListView) rootView.findViewById(R.id.listview_pieces_inventaire);
    inventairePiecesAdapterView.setAdapter(inventairePiecesAdapter);

    inventairePiecesAdapterView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
            piece = inventairePiecesAdapter.getItem(i);
            Intent intent = new Intent(getActivity(), PieceViewActivity.class);
            intent.putExtra("inventairePieces", inventairePieces);
            intent.putExtra("posClicked", i);
            startActivityForResult(intent, 1);

            Log.v("short clicked","pos: " + i);
        }
    });
    inventairePiecesAdapterView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
        @Override
        public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int i, long id) {
            piece = inventairePiecesAdapter.getItem(i);
            ConfirmeSuppDialogFragment dialogFrag = new ConfirmeSuppDialogFragment();
            bundle = new Bundle();
            bundle.putSerializable("piece",piece);
            bundle.putSerializable("inventairePieces",inventairePieces);
            dialogFrag.setArguments(bundle);
            dialogFrag.setTargetFragment(InventairePiecesFragment.this, 2);
            dialogFrag.show(getFragmentManager(), "dialog");

            Log.v("long clicked","pos: " + i);

            return true;
        }
    });


    return rootView;
}



@Override
public boolean onOptionsItemSelected(MenuItem item) {
    this.writeInventairePiece();
    return super.onOptionsItemSelected(item);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(resultCode == 1) {
        piece = (PieceModel) data.getSerializableExtra("piece");
        inventairePieces.addToInventairePieces(piece);
        this.writeInventairePiece();
        inventairePiecesAdapter.notifyDataSetChanged();
        printConfirmerState(piece, "ajoutée");
    }
    else if(resultCode == 2){
        inventairePieces.removeFromInventairePieces(piece);
        this.writeInventairePiece();
        inventairePiecesAdapter.notifyDataSetChanged();
        printConfirmerState(piece, "supprimée");
    }
}

private void writeInventairePiece(){
    try {
        FileOutputStream outputFile = this.getContext().openFileOutput("InventairePiece.ser", Context.MODE_PRIVATE);
        ObjectOutputStream outputStream = new ObjectOutputStream(outputFile);
        outputStream.writeObject(inventairePieces);
        outputStream.close();
        outputFile.close();
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

private void readInventairePiece(){
    try {
        FileInputStream inputFile = this.getContext().openFileInput("InventairePiece.ser");
        ObjectInputStream inputStream = new ObjectInputStream(inputFile);
        inventairePieces = (InventairePieces) inputStream.readObject();
        inputStream.close();
        inputFile.close();
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

private void printConfirmerState(PieceModel piece, String state){
    String confirm = state;
    for(int i = 0; i < inventairePieces.getInventairePieces().size(); i++) {
        if(i == inventairePieces.getInventairePieces().indexOf(piece) && state.equals("ajoutée")) {
            confirm = ("La pièce '" + piece.getNomPiece() + "' est " + state + ".");
        }else if(i == inventairePieces.getInventairePieces().indexOf(piece) && state.equals("supprimée")) {
            confirm = ("La pièce '" + piece.getNomPiece() + "' est " + state + ".");
        }
    }
    Toast.makeText(getContext(), confirm, Toast.LENGTH_SHORT).show();
}


/*@Override
public void updateResult(int result) {
    this.result = result;
}*/

}

我提前感谢你。

以防万一,这是我到目前为止的完整应用程序: My Project on gitHub

2 个答案:

答案 0 :(得分:0)

让我看看如果我做对了,你有一份物品清单吗?每当您选择任何项目时,您都会显示一个活动,其中包含该项目的所有详细信息(PieceModel);并且你想在这个片段中实现一个手势识别器,以便在上一个和下一个项目之间切换,而不必回到列表并紧紧选择新项目。

如果我的理解很好,你可以这样做:

  1. 实施手势识别器以处理片段上的左右滑动。
  2. 根据手势,您从创建列表适配器时使用的数据源中获取新项目对象(PieceModel),并更新存储在片段中的当前实例。
  3. 使用此&#34; new&#34;更新用户界面item,好像片段已从头开始加载。
  4. 瞧!!!,这里有一些链接:

    https://developer.android.com/training/gestures/detector.html

    http://guides.codepath.com/android/gestures-and-touch-events

    顺便说一句,当您将所选项目的索引传递给新活动时,您应将其检索为:

    position = getIntent().getIntExtra("posClicked");
    

    我强烈建议您传递项目ID而不是位置,顺便说一下,InventairePieces是否实现了Serializable接口?

答案 1 :(得分:0)

我还能够使用ViewPager和扩展FragmentStatePagerAdapter的内部类来实现滑动手势。

最终并没有那么复杂,但我真的很难让它在开始时工作,这就是为什么我也分享这些代码,希望它最终可以帮助某人。在这里获取代码 - &gt; My Project on github

以下是这些变化影响的两个类:

PieceViewActivity:

public class PieceViewActivity extends AppCompatActivity {
    /**
     * The {@link android.support.v4.view.PagerAdapter} that will provide fragments representing
     * each object in a collection. We use a {@link android.support.v4.app.FragmentStatePagerAdapter}
     * derivative, which will destroy and re-create fragments as needed, saving and restoring their
     * state in the process. This is important to conserve memory and is a best practice when
     * allowing navigation between objects in a potentially large collection.
     */
    PieceViewPagerAdapter pieceViewPagerAdapter;

    /**
     * The {@link android.support.v4.view.ViewPager} that will display the object collection.
     */
    ViewPager mViewPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_piece_view);

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.activity_piece_view_container, new PieceViewFragment())
                    .commit();

            // Create an adapter that when requested, will return a fragment representing an object in
            // the collection.
            pieceViewPagerAdapter = new PieceViewPagerAdapter(getSupportFragmentManager());
            // Set up the ViewPager, attaching the adapter.
            mViewPager = (ViewPager) findViewById(R.id.activity_piece_view_container);
            mViewPager.setAdapter(pieceViewPagerAdapter);

            //Receives the position of the item peviously clicked in the inventory list
            Intent intent = getIntent();
            mViewPager.setCurrentItem(intent.getIntExtra("posClicked", -1));
        }
    }

    /**
     * A {@link android.support.v4.app.FragmentStatePagerAdapter} that returns a fragment
     * representing an object in the collection.
     */
    public class PieceViewPagerAdapter extends FragmentStatePagerAdapter {

        //Accesses the InventairePieces class
        private InventairePieces inventairePieces;

        public PieceViewPagerAdapter(FragmentManager fm) {
            super(fm);

            Intent intent = getIntent();
            inventairePieces = (InventairePieces) intent.getSerializableExtra("inventairePieces");
        }

        /**
         * Gets the item position on swipe gestures
         * sends the detail fragment in a bundle
         * @param position the item position from swipe gesture
         * @return the new fragment details
         */
        @Override
        public Fragment getItem(int position) {
            Fragment fragment = new PieceViewFragment();
            Bundle args = new Bundle();
            args.putInt("position", position);
            fragment.setArguments(args);
            return fragment;
        }

        /**
         * Gets the size of the inventory from an intent
         * @return the size of the inventory
         */
        @Override
        public int getCount() {
            return inventairePieces.getInventairePieces().size();
        }
    }
}

PieveViewFragment:

public class PieceViewFragment extends Fragment {

    //Accesses the InventairePieces class
    private InventairePieces inventairePieces;
    //Accesses the PieceModel class
    private PieceModel piece;
    //The object's position in the inventory list
    private int positionClicked;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);

        //Gets the inventory from an intent
        Intent intent = getActivity().getIntent();
        positionClicked = intent.getIntExtra("posClicked", -1);
        inventairePieces = (InventairePieces) intent.getSerializableExtra("inventairePieces");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        final View rootView = inflater.inflate(R.layout.fragment_piece_view, container, false);

        //Gets the item position from a bundle
        Bundle args = getArguments();

        if(args != null) {
            positionClicked = args.getInt("position");
            piece = inventairePieces.getInventairePieces().get(positionClicked);

            //Sets the object's details
            ((TextView) rootView.findViewById(R.id.invCount_text)).setText(String.valueOf("(" + (positionClicked + 1) + "/" + inventairePieces.getInventairePieces().size()) + ")");
            ((TextView) rootView.findViewById(R.id.codePiece_text)).setText(String.valueOf("# " + piece.getCodePiece()));
            ((TextView) rootView.findViewById(R.id.nomPiece_text)).setText(piece.getNomPiece());
            ((TextView) rootView.findViewById(R.id.descriptionPiece_text)).setText(piece.getDescriptionPiece());
            ((TextView) rootView.findViewById(R.id.dimensionPiece_text)).setText(String.valueOf(piece.getDimensionPiece()) + " mm");
            ((TextView) rootView.findViewById(R.id.prixCoutantPiece_text)).setText(String.valueOf(piece.getPrixCoutantPiece()) + " $");
            ((TextView) rootView.findViewById(R.id.qtyPiece_text)).setText(String.valueOf(piece.getQtyPiece()));
            ((TextView) rootView.findViewById(R.id.typePiece_text)).setText(piece.getTypePiece());
            ((TextView) rootView.findViewById(R.id.categoriePiece_text)).setText(piece.getCategoriePiece());
        }
        return rootView;
    }
}