Android:GridLayout 的缩放 Out/In

Android: Zoom Out/In of a GridLayout

我正在制作扫雷游戏。我将我用于游戏的所有按钮都放在 GridLayout 中。

按钮最终将布局推到大于屏幕尺寸,所以我将布局放在一个 Horizo​​ntalScrollView 和一个 ScrollView 中。但是,当游戏结束时,我想缩小布局以便可以看到屏幕上的所有按钮。

我已经发布了相关文件,尽管最重要的内容是 fragment_grid.xml(包含 GridLayout 的 xml 文件)和 GridFragment::gameOver()(我想将 zoom-out代码)

fragment_grid.xml:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <HorizontalScrollView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:scrollbars="none"
        android:overScrollMode="never">

        <GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/grid"
            android:columnCount="10"
            android:rowCount="10">
        </GridLayout>
    </HorizontalScrollView>
</ScrollView>

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MainActivity"
    android:clickable="true"
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
</RelativeLayout>

GridFragment.java:

public class GridFragment extends Fragment {

    GridLayout gridLayout;
    public enum GameState{READY, PLAYING, WIN, LOSE}
    GameState gameState;    

    public GridFragment() {
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        gameState = GameState.READY;
        View view = inflater.inflate(R.layout.fragment_grid, container, false);
        gridLayout = (GridLayout)view.findViewById(R.id.grid);
        MButton[] buttons = generateGrid(100,25);
        for(MButton mButton:buttons){
            gridLayout.addView(mButton);
        }
        return view;
    }

    public MButton[] generateGrid(int gridSize, int numMines){
        Log.d("gridSize",""+gridSize);
        Log.d("numMines",""+numMines);
        ArrayList<Integer> array =  new ArrayList<Integer>();
        for (int i = 0; i < gridSize; i++) {
            array.add(new Integer(i));
        }
        Log.d("unsorted",array.toString());

        Collections.shuffle(array,new Random(System.currentTimeMillis()));
        MButton[] mButtons = new MButton[gridSize];
        MButton mButton;

        String numList = array.toString();
        Log.d("arraySize",""+array.size());
        Log.d("array",numList);

        for (int i = 0; i < gridSize; i++) {
            int x = array.get(i);
            mButton = new MButton(getActivity(),i, numMines > x);
            mButtons[i] = mButton;
        }
        return generateMineCount(mButtons);
    }

    private MButton[] generateMineCount(MButton[] mButtons){
        int rows = gridLayout.getRowCount();
        int columns = gridLayout.getColumnCount();
        for (int i = 0; i < mButtons.length; i++) {
            if((i/columns) > 0){if(mButtons[i-columns].isMine()){mButtons[i].addAdjacentMines();}}
            if((i/columns) < rows-1){if(mButtons[i+columns].isMine()){mButtons[i].addAdjacentMines();}}
            if((i%rows) > 0){if(mButtons[i-1].isMine()){mButtons[i].addAdjacentMines();}}
            if((i%rows) < columns-1){if(mButtons[i+1].isMine()){mButtons[i].addAdjacentMines();}}
            if( ((i/columns) > 0)&&((i%rows) > 0) ){if(mButtons[i-columns-1].isMine()){mButtons[i].addAdjacentMines();}}
            if( ((i/columns) < rows-1)&&((i%rows) > 0) ){if(mButtons[i+columns-1].isMine()){mButtons[i].addAdjacentMines();}}
            if( ((i/columns) > 0)&&((i%rows) < columns-1) ){if(mButtons[i-columns+1].isMine()){mButtons[i].addAdjacentMines();}}
            if( ((i/columns) < rows-1)&&((i%rows) < columns-1) ){if(mButtons[i+columns+1].isMine()){mButtons[i].addAdjacentMines();}}
            if(!mButtons[i].isMine() && mButtons[i].getAdjacentMines() > 0){mButtons[i].displayMines();}
        }
        return mButtons;
    }

    public void startGame(){
            gameState = GameState.PLAYING;
    }

    public void gameOver(){
        gameState = GameState.LOSE;
        for (int i = 0; i < gridLayout.getChildCount(); i++) {
            MButton mb = (MButton)gridLayout.getChildAt(i);
            mb.setOnTouchListener(null);
            //insert zoom-out layout code here    
        }
        gridLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
    }

}

MButton.java:

public class MButton extends Button {

    public enum State{NORMAL, OPENED, FLAGGED, UNKNOWN}
    State state;
    boolean longPress;
    long startTime = 0;
    int num;
    boolean mine;
    final float scale = getContext().getResources().getDisplayMetrics().density;
    int adjacentMines = 0;
    MainActivity mainActivity = (MainActivity)getContext();
    GridFragment gridFragment = (GridFragment)mainActivity.getFragmentManager().findFragmentByTag("gridFragment");
    ImageButton startButton = (ImageButton)(mainActivity.getActionBar()).getCustomView().findViewById(R.id.actionBarLogo);

    static Handler timerHandler = new Handler();
    Runnable timerRunnable = new Runnable() {

        @Override
        public void run() {
            long milliseconds = System.currentTimeMillis() - startTime;
            longPress = false;
            if(milliseconds >= 1500) {
                longPressTile();
                timerHandler.removeCallbacks(timerRunnable);
            }
            else
                timerHandler.postDelayed(this, 0);
        }
    };

    public MButton(Context context, int i, boolean m) {
        super(context);
        create(i, m);
    }

    public MButton(Context context, AttributeSet attrs, int i, boolean m) {
        super(context, attrs);
        create(i, m);
    }

    public MButton(Context context, AttributeSet attrs, int defStyleAttr, int i, boolean m) {
        super(context, attrs, defStyleAttr);
        create(i, m);
    }

    private void longPressTile(){
        longPress = true;
        setBackgroundResource(R.drawable.tile);
        startButton.setImageResource(R.drawable.smiley);
        if(state == State.FLAGGED || state == State.UNKNOWN){
            state = State.NORMAL;
            setText("");
        }
        else if(state == State.NORMAL){
            state = State.FLAGGED;
            setText("F");
        }
    }


    private boolean isInGrayArea(float xCoord, float yCoord){
        int xValue = (int) ((xCoord/scale)+0.5);
        int yValue = (int) ((yCoord/scale)+0.5);
        Log.d("button"+num,"("+xValue+","+yValue+")");
        Log.d("size","("+Integer.toString(getWidth())+","+Integer.toString(getHeight())+")");
        return (xValue >= 5)&&(xValue < 45)&&(yValue >= 5)&&(yValue < 45);
    }

    public void addAdjacentMines(){
        adjacentMines++;
    }

    public boolean isMine(){
        return mine;
    }

    public void displayMines(){
        if(mine)
            setText("M");
        else if(hasAdjacentMines())
            setText(""+adjacentMines);
        else
            setText("");
    }

    public int getAdjacentMines(){
        return adjacentMines;
    }

    public boolean hasAdjacentMines(){ return getAdjacentMines() > 0;}

    private void openAdjacentButtons(){

        GridLayout gridLayout = gridFragment.gridLayout;
        int rows = gridLayout.getRowCount();
        int columns = gridLayout.getColumnCount();
        if((num/columns) > 0){((MButton)gridLayout.getChildAt(num-columns)).revealButton();}
        if((num/columns) < rows-1){((MButton)gridLayout.getChildAt(num+columns)).revealButton();}
        if((num%rows) > 0){((MButton)gridLayout.getChildAt(num-1)).revealButton();}
        if((num%rows) < columns-1){((MButton)gridLayout.getChildAt(num+1)).revealButton();}//
        if( ((num/columns) > 0)&&((num%rows) > 0) ){((MButton)gridLayout.getChildAt(num-columns-1)).revealButton();}
        if( ((num/columns) < rows-1)&&((num%rows) > 0) ){((MButton)gridLayout.getChildAt(num+columns-1)).revealButton();}
        if( ((num/columns) > 0)&&((num%rows) < columns-1) ){((MButton)gridLayout.getChildAt(num-columns+1)).revealButton();}
        if( ((num/columns) < rows-1)&&((num%rows) < columns-1) ){((MButton)gridLayout.getChildAt(num+columns+1)).revealButton();}

    }

    public void revealButton() {
        if (state != State.OPENED){
            state = State.OPENED;
            displayMines();
            if (!isMine() && !hasAdjacentMines())
                openAdjacentButtons();
            else if(isMine()){
                startButton.setImageResource(R.drawable.smiley3);
                gridFragment.gameOver();
            }
            setBackgroundResource(R.drawable.tile3);

        }
    }

    private void create(int i, boolean m){
        state = State.NORMAL;
        num = i;
        mine = m;
        setBackgroundResource(R.drawable.tile);
        setLayoutParams(new LinearLayout.LayoutParams(150,150));

        if(mine){
            setText("m");
        }


        this.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent me) {
                if(isInGrayArea(me.getX(), me.getY())){
                    switch (me.getAction()) {
                        case MotionEvent.ACTION_DOWN: {
                            if (state != State.OPENED) {
                                if(gridFragment.gameState == GridFragment.GameState.READY)
                                    gridFragment.startGame();
                                startTime = System.currentTimeMillis();
                                v.setBackgroundResource(R.drawable.tile2);
                                startButton.setImageResource(R.drawable.smiley2);
                                timerHandler.postDelayed(timerRunnable, 0);
                            }
                            return true;
                        }
                        case MotionEvent.ACTION_UP: {
                            if (!longPress) {
                                startButton.setImageResource(R.drawable.smiley);
                                switch(state){
                                    case NORMAL:{
                                        revealButton();
                                        break;
                                    }
                                    case UNKNOWN:{
                                        state = State.UNKNOWN;
                                        v.setBackgroundResource(R.drawable.tile);
                                        setText("?");
                                        break;
                                    }
                                    case FLAGGED:{
                                        state = State.FLAGGED;
                                        v.setBackgroundResource(R.drawable.tile);
                                        setText("F");
                                    }
                                }
                            }
                            timerHandler.removeCallbacks(timerRunnable);
                            return true;
                        }
                    }
                }
                return false;
            }

        });
    }

}

MainActivity.java

public class MainActivity extends Activity {

    private boolean mInit = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        final ActionBar actionBar = getActionBar();
        actionBar.setCustomView(R.layout.actionbar);
        actionBar.setDisplayShowTitleEnabled(false);
        actionBar.setDisplayShowCustomEnabled(true);
        actionBar.setDisplayUseLogoEnabled(false);
        actionBar.setDisplayShowHomeEnabled(false);

        Typeface myTypeface = Typeface.createFromAsset(getAssets(), "fonts/digital-7.ttf");
        TextView myTextView = (TextView)findViewById(R.id.textView1);
        TextView myTopTextView = (TextView)findViewById(R.id.topTextView1);
        myTextView.setTypeface(myTypeface);
        myTopTextView.setTypeface(myTypeface);

        if (findViewById(R.id.fragment_container) != null){
            if (savedInstanceState != null) {
                return;
            }
        }
    }

    private void initial(){

        GridFragment gFragment = new GridFragment();

        gFragment.setArguments(getIntent().getExtras());

        getFragmentManager().beginTransaction().add(R.id.fragment_container, gFragment,"gridFragment").commit();

    }

    @Override
    protected void onStart() {
        if (!mInit) {
            mInit = true;
            initial();
        }
        super.onStart();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

P.S。新年快乐!

我想这会有所帮助:Android - zoom in/out RelativeLayout with spread/pinch 您可以为 gridLayout 应用相同的实现,祝您好运 :) 和新年快乐

我知道我花了 6 个月的时间才完成这项工作。 class 应该适用于任何视图或视图组。只需扩展任何需要缩放的视图或视图组。 https://github.com/Xjasz/AndroidZoomableViewGroup