mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-09 21:52:05 +08:00
Simple tutorial (without fragments, ViewPagers and vertical layout)
This commit is contained in:
@@ -1,108 +0,0 @@
|
||||
package com.hololo.tutorial.library;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
public class Step implements Parcelable {
|
||||
|
||||
private String title;
|
||||
private String content;
|
||||
private String summary;
|
||||
private int drawable;
|
||||
private int backgroundColor;
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public int getDrawable() {
|
||||
return drawable;
|
||||
}
|
||||
|
||||
public int getBackgroundColor() {
|
||||
return backgroundColor;
|
||||
}
|
||||
|
||||
public String getSummary() {
|
||||
return summary;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private Step step;
|
||||
|
||||
public Builder() {
|
||||
step = new Step();
|
||||
}
|
||||
|
||||
public Step build() {
|
||||
return step;
|
||||
}
|
||||
|
||||
public Builder setTitle(String title) {
|
||||
step.title = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setContent(String content) {
|
||||
step.content = content;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSummary(String summary) {
|
||||
step.summary = summary;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setDrawable(int drawable) {
|
||||
step.drawable = drawable;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setBackgroundColor(int backgroundColor) {
|
||||
step.backgroundColor = backgroundColor;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(this.title);
|
||||
dest.writeString(this.content);
|
||||
dest.writeString(this.summary);
|
||||
dest.writeInt(this.drawable);
|
||||
dest.writeInt(this.backgroundColor);
|
||||
}
|
||||
|
||||
public Step() {
|
||||
}
|
||||
|
||||
protected Step(Parcel in) {
|
||||
this.title = in.readString();
|
||||
this.content = in.readString();
|
||||
this.summary = in.readString();
|
||||
this.drawable = in.readInt();
|
||||
this.backgroundColor = in.readInt();
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<Step> CREATOR = new Parcelable.Creator<Step>() {
|
||||
@Override
|
||||
public Step createFromParcel(Parcel source) {
|
||||
return new Step(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Step[] newArray(int size) {
|
||||
return new Step[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package com.hololo.tutorial.library;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import in.celest.xash3d.hl.R;
|
||||
|
||||
public class StepFragment extends Fragment {
|
||||
|
||||
private TextView title;
|
||||
private TextView content;
|
||||
private TextView summary;
|
||||
private ImageView imageView;
|
||||
private LinearLayout layout;
|
||||
|
||||
private Step step;
|
||||
|
||||
static StepFragment createFragment(Step step) {
|
||||
StepFragment fragment = new StepFragment();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable("step", step);
|
||||
fragment.setArguments(bundle);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
step = getArguments().getParcelable("step");
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_step, container, false);
|
||||
|
||||
initViews(view);
|
||||
initData();
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
title.setText(step.getTitle());
|
||||
content.setText(step.getContent());
|
||||
summary.setText(step.getSummary());
|
||||
imageView.setImageResource(step.getDrawable());
|
||||
layout.setBackgroundColor(step.getBackgroundColor());
|
||||
}
|
||||
|
||||
private void initViews(View view) {
|
||||
title = (TextView) view.findViewById(R.id.title);
|
||||
content = (TextView) view.findViewById(R.id.content);
|
||||
summary = (TextView) view.findViewById(R.id.summary);
|
||||
imageView = (ImageView) view.findViewById(R.id.image);
|
||||
layout = (LinearLayout) view.findViewById(R.id.container);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.hololo.tutorial.library;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class StepPagerAdapter extends FragmentPagerAdapter {
|
||||
private List<Step> stepList;
|
||||
|
||||
public StepPagerAdapter(FragmentManager fm, List<Step> stepList) {
|
||||
super(fm);
|
||||
this.stepList = stepList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
return StepFragment.createFragment(stepList.get(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return stepList.size();
|
||||
}
|
||||
}
|
||||
@@ -1,216 +0,0 @@
|
||||
package com.hololo.tutorial.library;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
// import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import su.xash.fwgslib.FWGSLib;
|
||||
import in.celest.xash3d.hl.R;
|
||||
|
||||
public class TutorialActivity extends FragmentActivity /* AppCompatActivity */ implements View.OnClickListener {
|
||||
|
||||
private List<Step> steps;
|
||||
private StepPagerAdapter adapter;
|
||||
|
||||
private ViewPager pager;
|
||||
private Button next, prev;
|
||||
private LinearLayout indicatorLayout;
|
||||
private FrameLayout containerLayout;
|
||||
private RelativeLayout buttonContainer;
|
||||
|
||||
private int currentItem;
|
||||
|
||||
private String prevText, nextText, finishText, cancelText;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
if( FWGSLib.sdk >= 21 ) // material
|
||||
setTheme(0x0103022e); // Theme_Material_NoActionBar
|
||||
else
|
||||
setTheme(0x01030006); // Theme_NoTitleBar
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_tutorial);
|
||||
steps = new ArrayList<Step>();
|
||||
initTexts();
|
||||
initViews();
|
||||
initAdapter();
|
||||
}
|
||||
|
||||
private void initTexts() {
|
||||
prevText = getString(R.string.prev);
|
||||
cancelText = getString(R.string.cancel);
|
||||
finishText = getString(R.string.finish);
|
||||
nextText = getString(R.string.next);
|
||||
}
|
||||
|
||||
private void initAdapter() {
|
||||
adapter = new StepPagerAdapter(getSupportFragmentManager(), steps);
|
||||
pager.setAdapter(adapter);
|
||||
pager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
currentItem = position;
|
||||
controlPosition(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void changeStatusBarColor(int backgroundColor) {
|
||||
// Window window = getWindow();
|
||||
// window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||
// window.addFlags(0x80000000) //WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
|
||||
// window.setStatusBarColor(backgroundColor);
|
||||
}
|
||||
|
||||
private void controlPosition(int position) {
|
||||
notifyIndicator();
|
||||
if (position == steps.size() - 1) {
|
||||
next.setText(finishText);
|
||||
prev.setText(prevText);
|
||||
} else if (position == 0) {
|
||||
prev.setText(cancelText);
|
||||
next.setText(nextText);
|
||||
} else {
|
||||
prev.setText(prevText);
|
||||
next.setText(nextText);
|
||||
}
|
||||
|
||||
containerLayout.setBackgroundColor(steps.get(position).getBackgroundColor());
|
||||
buttonContainer.setBackgroundColor(steps.get(position).getBackgroundColor());
|
||||
}
|
||||
|
||||
private void initViews() {
|
||||
currentItem = 0;
|
||||
|
||||
pager = (ViewPager) findViewById(R.id.viewPager);
|
||||
next = (Button) findViewById(R.id.next);
|
||||
prev = (Button) findViewById(R.id.prev);
|
||||
indicatorLayout = (LinearLayout) findViewById(R.id.indicatorLayout);
|
||||
containerLayout = (FrameLayout) findViewById(R.id.containerLayout);
|
||||
buttonContainer = (RelativeLayout) findViewById(R.id.buttonContainer);
|
||||
|
||||
next.setOnClickListener(this);
|
||||
prev.setOnClickListener(this);
|
||||
}
|
||||
|
||||
public void addFragment(Step step) {
|
||||
steps.add(step);
|
||||
adapter.notifyDataSetChanged();
|
||||
notifyIndicator();
|
||||
controlPosition(currentItem);
|
||||
}
|
||||
|
||||
public void addFragment(Step step, int position) {
|
||||
steps.add(position, step);
|
||||
adapter.notifyDataSetChanged();
|
||||
notifyIndicator();
|
||||
}
|
||||
|
||||
public void notifyIndicator() {
|
||||
if (indicatorLayout.getChildCount() > 0)
|
||||
indicatorLayout.removeAllViews();
|
||||
|
||||
for (int i = 0; i < steps.size(); i++) {
|
||||
ImageView imageView = new ImageView(this);
|
||||
imageView.setPadding(8, 8, 8, 8);
|
||||
int drawable = R.drawable.circle_black;
|
||||
if (i == currentItem)
|
||||
drawable = R.drawable.circle_white;
|
||||
|
||||
imageView.setImageResource(drawable);
|
||||
|
||||
final int finalI = i;
|
||||
imageView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
changeFragment(finalI);
|
||||
}
|
||||
});
|
||||
|
||||
indicatorLayout.addView(imageView);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (currentItem == 0) {
|
||||
super.onBackPressed();
|
||||
} else {
|
||||
changeFragment(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v.getId() == R.id.next) {
|
||||
changeFragment(true);
|
||||
} else if (v.getId() == R.id.prev) {
|
||||
changeFragment(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void changeFragment(int position) {
|
||||
pager.setCurrentItem(position, true);
|
||||
}
|
||||
|
||||
private void changeFragment(boolean isNext) {
|
||||
int item = currentItem;
|
||||
if (isNext) {
|
||||
item++;
|
||||
} else {
|
||||
item--;
|
||||
}
|
||||
|
||||
if (item < 0 || item == steps.size()) {
|
||||
finishTutorial();
|
||||
} else
|
||||
pager.setCurrentItem(item, true);
|
||||
}
|
||||
|
||||
public void finishTutorial() {
|
||||
finish();
|
||||
}
|
||||
|
||||
public void setPrevText(String text) {
|
||||
prevText = text;
|
||||
}
|
||||
|
||||
public void setNextText(String text) {
|
||||
nextText = text;
|
||||
}
|
||||
|
||||
public void setFinishText(String text) {
|
||||
finishText = text;
|
||||
}
|
||||
|
||||
public void setCancelText(String text) {
|
||||
cancelText = text;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,60 +1,208 @@
|
||||
package in.celest.xash3d;
|
||||
|
||||
import com.hololo.tutorial.library.TutorialActivity;
|
||||
import com.hololo.tutorial.library.Step;
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
// import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.graphics.Color;
|
||||
import android.app.*;
|
||||
import android.os.*;
|
||||
import android.view.*;
|
||||
import android.widget.*;
|
||||
import in.celest.xash3d.hl.*;
|
||||
import java.util.*;
|
||||
import su.xash.fwgslib.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import in.celest.xash3d.hl.R;
|
||||
|
||||
public class XashTutorialActivity extends TutorialActivity
|
||||
public class XashTutorialActivity extends Activity implements View.OnClickListener
|
||||
{
|
||||
private Button next, prev;
|
||||
private LinearLayout indicatorLayout;
|
||||
private FrameLayout containerLayout;
|
||||
private RelativeLayout buttonContainer;
|
||||
private TextView title;
|
||||
private TextView text;
|
||||
private ImageView drawable;
|
||||
|
||||
private int currentItem;
|
||||
|
||||
private int prevText, nextText, finishText, cancelText;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if( FWGSLib.sdk >= 21 ) // material
|
||||
setTheme(0x0103022e); // Theme_Material_NoActionBar
|
||||
else
|
||||
setTheme(0x01030006); // Theme_NoTitleBar
|
||||
setContentView(R.layout.activity_tutorial);
|
||||
initTexts();
|
||||
initViews();
|
||||
changeFragment(0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
addFragment(new Step.Builder().setTitle(getString(R.string.page_title0))
|
||||
.setContent(getString(R.string.page_content0))
|
||||
.setBackgroundColor(Color.parseColor("#555555")) // int background color
|
||||
.setDrawable(R.drawable.page0) // int top drawable
|
||||
.build());
|
||||
private void initTexts() {
|
||||
prevText = R.string.prev;
|
||||
cancelText = R.string.cancel;
|
||||
finishText = R.string.finish;
|
||||
nextText = R.string.next;
|
||||
}
|
||||
|
||||
addFragment(new Step.Builder().setTitle(getString(R.string.page_title1))
|
||||
.setContent(getString(R.string.page_content1))
|
||||
.setBackgroundColor(Color.parseColor("#555555")) // int background color
|
||||
.setDrawable(R.drawable.page1_en) // int top drawable
|
||||
.build());
|
||||
addFragment(new Step.Builder().setTitle(getString(R.string.page_title2))
|
||||
.setContent(getString(R.string.page_content2))
|
||||
.setBackgroundColor(Color.parseColor("#555555")) // int background color
|
||||
.setDrawable(R.drawable.page2_en) // int top drawable
|
||||
.build());
|
||||
addFragment(new Step.Builder().setTitle(getString(R.string.page_title3))
|
||||
.setContent(getString(R.string.page_content3))
|
||||
.setBackgroundColor(Color.parseColor("#555555")) // int background color
|
||||
.setDrawable(R.drawable.page3_en) // int top drawable
|
||||
.build());
|
||||
addFragment(new Step.Builder().setTitle(getString(R.string.page_title4))
|
||||
.setContent(getString(R.string.page_content4))
|
||||
.setBackgroundColor(Color.parseColor("#555555")) // int background color
|
||||
.setDrawable(R.drawable.page4_en)
|
||||
.build());
|
||||
private void initAdapter() {
|
||||
/*adapter = new StepPagerAdapter(getSupportFragmentManager(), steps);
|
||||
pager.setAdapter(adapter);
|
||||
pager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
currentItem = position;
|
||||
controlPosition(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
}
|
||||
});*/
|
||||
}
|
||||
|
||||
private void changeStatusBarColor(int backgroundColor) {
|
||||
// Window window = getWindow();
|
||||
// window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||
// window.addFlags(0x80000000) //WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
|
||||
// window.setStatusBarColor(backgroundColor);
|
||||
}
|
||||
|
||||
private void controlPosition( boolean last) {
|
||||
notifyIndicator();
|
||||
if (last) {
|
||||
next.setText(finishText);
|
||||
prev.setText(prevText);
|
||||
} else if ( currentItem == 0) {
|
||||
prev.setText(cancelText);
|
||||
next.setText(nextText);
|
||||
} else {
|
||||
prev.setText(prevText);
|
||||
next.setText(nextText);
|
||||
}
|
||||
|
||||
//containerLayout.setBackgroundColor(steps.get(position).getBackgroundColor());
|
||||
//buttonContainer.setBackgroundColor(steps.get(position).getBackgroundColor());
|
||||
}
|
||||
|
||||
private void initViews() {
|
||||
currentItem = 0;
|
||||
|
||||
// pager = (ViewPager) findViewById(R.id.viewPager);
|
||||
next = (Button) findViewById(R.id.next);
|
||||
prev = (Button) findViewById(R.id.prev);
|
||||
indicatorLayout = (LinearLayout) findViewById(R.id.indicatorLayout);
|
||||
containerLayout = (FrameLayout) findViewById(R.id.containerLayout);
|
||||
buttonContainer = (RelativeLayout) findViewById(R.id.buttonContainer);
|
||||
title = (TextView) findViewById(R.id.title);
|
||||
text = (TextView) findViewById(R.id.content);
|
||||
drawable = (ImageView) findViewById(R.id.image);
|
||||
|
||||
next.setOnClickListener(this);
|
||||
prev.setOnClickListener(this);
|
||||
}
|
||||
|
||||
|
||||
public void notifyIndicator() {
|
||||
if (indicatorLayout.getChildCount() > 0)
|
||||
indicatorLayout.removeAllViews();
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
ImageView imageView = new ImageView(this);
|
||||
imageView.setPadding(8, 8, 8, 8);
|
||||
int drawable = R.drawable.circle_black;
|
||||
if (i == currentItem)
|
||||
drawable = R.drawable.circle_white;
|
||||
|
||||
imageView.setImageResource(drawable);
|
||||
|
||||
final int finalI = i;
|
||||
imageView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
changeFragment(finalI);
|
||||
}
|
||||
});
|
||||
|
||||
indicatorLayout.addView(imageView);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (currentItem == 0) {
|
||||
super.onBackPressed();
|
||||
} else {
|
||||
changeFragment(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v.getId() == R.id.next) {
|
||||
changeFragment(true);
|
||||
} else if (v.getId() == R.id.prev) {
|
||||
changeFragment(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void changeFragment(int position) {
|
||||
currentItem = position;
|
||||
updateStep();
|
||||
}
|
||||
|
||||
private void changeFragment(boolean isNext) {
|
||||
if (isNext) {
|
||||
currentItem++;
|
||||
} else {
|
||||
currentItem--;
|
||||
}
|
||||
updateStep();
|
||||
}
|
||||
|
||||
|
||||
void updateStep()
|
||||
{
|
||||
int titleres = getResources().getIdentifier("page_title" + String.valueOf(currentItem), "string", getPackageName());
|
||||
|
||||
if( titleres == 0 )
|
||||
{
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
int titlenext = getResources().getIdentifier("page_title" + String.valueOf(currentItem+1), "string", getPackageName());
|
||||
int contentres = getResources().getIdentifier("page_content" + String.valueOf(currentItem), "string", getPackageName());
|
||||
int drawableres = getResources().getIdentifier("page" + String.valueOf(currentItem), "drawable", getPackageName());
|
||||
if( drawableres == 0)
|
||||
drawableres = getResources().getIdentifier("page" + String.valueOf(currentItem) + "_" + Locale.getDefault().getLanguage(), "drawable", getPackageName());
|
||||
if( drawableres == 0 )
|
||||
drawableres = getResources().getIdentifier("page" + String.valueOf(currentItem) + "_en", "drawable", getPackageName());
|
||||
|
||||
title.setText(titleres);
|
||||
text.setText(contentres);
|
||||
drawable.setImageResource(drawableres);
|
||||
controlPosition(titlenext == 0);
|
||||
}
|
||||
|
||||
public void setPrevText(int text) {
|
||||
prevText = text;
|
||||
}
|
||||
|
||||
public void setNextText(int text) {
|
||||
nextText = text;
|
||||
}
|
||||
|
||||
public void setFinishText(int text) {
|
||||
finishText = text;
|
||||
}
|
||||
|
||||
public void setCancelText(int text) {
|
||||
cancelText = text;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user